leaf leftleaf right

Courses & Tutorials

Adel Nasim Youtube’s Courses

C++

Welcome to the World of C++ Programming!

Hello, I’m Adel Nasim, the creator of Adel Nasim YouTube Channel, and I’m excited to guide you through the essentials of C++ programming. Whether you’re a novice or looking to deepen your skills, this written course, alongside my YouTube tutorials, is your comprehensive resource for mastering C++. We’ll cover everything from the basics to advanced concepts, ensuring you gain both theoretical knowledge and practical coding skills.

Get ready for a journey that blends theory with hands-on examples, equipping you with the confidence to tackle real-world challenges. Whether you’re building your programming foundation or enhancing existing skills, let’s dive into the world of C++ together. Happy coding!

Introduction

C++ is a cross-platform programming language that can be used to create high-performance applications. It is a general-purpose language, which means it can be used to develop a wide variety of software, including operating systems, games, embedded systems, and more.

C++ is a popular choice for developing high-performance applications because it gives programmers a high level of control over system resources and memory. It is also a very efficient language, which means that C++ programs typically run faster than programs written in other languages.

C++ is a relatively complex language to learn, but it is also a very powerful language. Once you have mastered the basics of C++, you will be able to develop almost any type of software you can imagine.

Why is C++?

C++ is one of the most popular programming languages in the world for a reason. It is a powerful, versatile, and efficient language that can be used to create a wide variety of software.

Here are just a few of the reasons why C++ is so popular:

  • Performance: C++ programs are typically very fast and efficient. This is because C++ gives programmers a high level of control over system resources and memory.
  • Versatility: C++ can be used to develop a wide variety of software, from operating systems to games to embedded systems.
  • Portability: C++ programs can be compiled and run on a variety of platforms, including Windows, macOS, Linux, and more.
  • Community: C++ has a large and active community of developers. This means that there is a wealth of resources available to help you learn and use C++.

Difference between C and C++

C++ was developed as an extension of the C programming language. Both languages have a similar syntax, but C++ adds a number of new features, including:

  • Classes and objects: C++ supports classes and objects, which provide a way to encapsulate data and code into reusable units.
  • Templates: C++ templates allow you to create generic functions and classes that can be used with different data types.
  • Exception handling: C++ provides exception handling features that allow you to deal with errors in a structured way.

Get Started

If you are interested in learning C++, there are a number of resources available to help you get started. There are many good books and tutorials available online, and there are also a number of C++ communities where you can ask for help and advice.

Once you have learned the basics of C++, you can start developing your own applications. There are a number of different C++ compilers and development environments available, so you can choose the one that best suits your needs.

Conclusion

C++ is a powerful and versatile programming language that can be used to create a wide variety of software. It is a popular choice for developing high-performance applications, and it is also a good choice for beginners because it is relatively easy to learn.

Getting Started

What is C++?

C++ is a general-purpose programming language that is used to create a wide range of applications, including operating systems, games, embedded systems, and web applications. C++ is known for its speed, efficiency, and flexibility.

Getting started with C++

To get started with C++, you will need to install a C++ compiler and IDE. A compiler is a program that converts C++ code into machine code that can be executed by a computer. An IDE is an integrated development environment that provides a variety of tools for writing, editing, compiling, and debugging C++ code.

Installing a C++ compiler and IDE

There are many different C++ compilers and IDEs available. For this tutorial, we will use Visual Studio for C++. Visual Studio is a free and powerful IDE that provides comprehensive support for C++ development.

To install Visual Studio for C++, visit the Visual Studio website and download the latest version.

Writing your first C++ program

Once you have installed Visual Studio for C++, you can start writing your first C++ program. To do this, create a new project and select the “C++ Console App” template.

Once you have created a new project, you can start writing C++ code in the main source file. The main source file is typically named main.cpp.

Here is a simple example of a C++ program:

C++
#include <iostream>
int main() {
  std::cout << "Hello, world!" << std::endl;
  return 0;
}

This program prints the message “Hello, world!” to the console.

Once you have written your C++ program, you can compile and run it by pressing F5.

Learning more about C++

Now that you have written your first C++ program, you can start learning more about the language. There are many resources available online and in libraries.

Here are a few tips for learning C++:

  • Start with the basics. Learn about variables, data types, operators, functions, and control flow statements.
  • Find a good tutorial or book. There are many resources available that can teach you the basics of C++.
  • Practice regularly. The best way to learn C++ is by writing code. Try to write simple programs at first, and gradually work your way up to more complex programs.
  • Use an IDE. An IDE can make it easier to write, edit, compile, and debug C++ code.

Conclusion

Getting started with C++ can be daunting, but it is also rewarding. C++ is a powerful and versatile language that can be used to create a wide range of applications.

By following the tips in this guide, you can start learning C++ today and start creating your own applications.

First Project in C++

 

Example:

C++

#include <iostream>
int main()
{ 
    std::cout << "Welcome to C++";
    return 0;
}


This is a simple C++ program that prints the message “Welcome to C++” to the console.

  • #include <iostream>: This line tells the compiler to include the header file iostream. This header file contains declarations for the standard input/output library.
  • int main(): This line defines the main function. The main function is the entry point for all C++ programs.
  • std::cout << “Welcome to C++”;: This line prints the message “Welcome to C++” to the console using the std::cout object.
  • return 0;: This line returns the value 0 from the main function. This indicates that the program terminated successfully.

When you compile and run this program, the following output will be printed to the console:

Welcome to C++

This is a very simple example of a C++ program, but it illustrates some of the basic concepts of the language, such as header files, functions, and input/output.

Escape Sequence

Escape sequences are special characters that are used to represent non-printing characters or to control the behavior of output streams. They are prefixed with a backslash (\).

Types of Escape Sequences

There are three types of escape sequences in C++:

  • Character escape sequences: These escape sequences represent non-printing characters, such as newline, tab, and backspace.
  • Hexadecimal escape sequences: These escape sequences represent characters using their hexadecimal values.
  • Octal escape sequences: These escape sequences represent characters using their octal values.

Common Escape Sequences

Here are some of the most common escape sequences in C++:

Escape Sequence Description
\n Newline
\t Tab
\\ Backslash
\" Double quote
\' Single quote
\? Question mark
\a Alert
\b Backspace
\f Form feed
\r Carriage return
\v Vertical tab
\x Hexadecimal escape sequence
\NNN Octal escape sequence

Using Escape Sequences

Escape sequences can be used in string and character literals. For example, the following code prints the string “Hello, world!” followed by a newline character:

C++
std::cout << "Hello, world!" << std::endl;

The std::endl object represents the newline character. It is equivalent to the escape sequence \n.

Escape sequences can also be used to represent non-printing characters, such as the tab character. For example, the following code prints the string “Hello, world!” followed by a tab character:

C++
std::cout << "Hello, world!" << '\t';

Example

Here are some more examples of how to use escape sequences in C++:

C++
// Print the string "This is a quote \" inside a string." 
std::cout << "This is a quote \" inside a string."; 

// Print the character 'a' with a backspace before it. 
std::cout << '\b' << 'a';

// Print the string "Hello, world!" followed by a newline character and a tab character. 
std::cout << "Hello, world!" << std::endl << '\t';
Conclusion

Escape sequences are a powerful tool that can be used to control the behavior of output streams and to represent non-printing characters in C++.

Variables vs Data type

Variables vs Data types in C++

Variables

Variables are named memory locations that can store data. They are declared using the var_name : data_type syntax. For example, the following code declares a variable named my_integer that can store an integer value:

C++
int my_integer;

Once a variable is declared, it can be used to store and retrieve data. For example, the following code assigns the value 10 to the my_integer variable:

C++
my_integer = 10;

The following code prints the value of the my_integer variable to the console:

C++
std::cout << my_integer << std::endl;

Output:

10

Data types

Data types define the type of data that a variable can store. C++ has a variety of data types, including integers, floating-point numbers, characters, strings, and Boolean values.

Here are some examples of data types in C++:

  • int: Stores integer values
  • float: Stores floating-point numbers
  • char: Stores a single character
  • string: Stores a sequence of characters
  • bool: Stores a Boolean value (true or false)

When a variable is declared, it must be assigned a data type. This tells the compiler how much memory to allocate for the variable and what type of data it can store.

For example, the following code declares a variable named my_string that can store a string value:

C++
string my_string;

The string data type is a special data type that is used to store sequences of characters.

Example

Here is an example of how to use variables and data types in C++:

C++
int my_integer = 10;
float my_floating_point_number = 3.14159;
char my_character = 'a';
string my_string = "Hello, world!";
bool my_boolean_value = true;

// Print the values of the variables.
std::cout << my_integer << std::endl;
std::cout << my_floating_point_number << std::endl;
std::cout << my_character << std::endl;
std::cout << my_string << std::endl;
std::cout << my_boolean_value << std::endl;

Output:

10
3.14159
a
Hello, world!
true

Variables and data types are essential concepts in C++. By understanding how they work, you can write more efficient and effective code.

Priorities & Calculations in C++

C++ has a set of operator precedence rules that determine the order in which expressions are evaluated. Operators with higher precedence are evaluated before operators with lower precedence.

Here is a table of the operator precedence rules in C++:

Operator Group Operators
Parentheses ()[]{}
Unary operators +-!~*&++--sizeofcasttype-name
Multiplication, division, and modulus */%
Addition and subtraction +-
Bitwise AND &
Bitwise OR |
Bitwise XOR ^
Equality and inequality ==!=
Less than, less than or equal to, greater than, greater than or equal to <<=>>=
Logical AND &&
Logical OR ||
Assignment =+=-=*=/=%=&=, `
Conditional operator ? :
Comma ,

When evaluating an expression, operators with the highest precedence are evaluated first, followed by operators with lower precedence.

Here are some examples of how operator precedence works in C++:

// Evaluates to 13.
int x = 5 * 2 + 3;

// Evaluates to 11.
int y = 5 + 2 * 3;

// Evaluates to true.
bool z = 5 < 10 && 10 > 5;

// Evaluates to false.
bool w = 5 > 10 || 10 < 5;

It is important to be aware of operator precedence when writing C++ code. Otherwise, you may get unexpected results.

Here is another example of how operator precedence can be used to control the order of evaluation:

// Evaluates to 16.
int a = (5 + 3) * 2;

// Evaluates to 11.
int b = 5 + (3 * 2);

In the first expression, the addition operator (+) has higher precedence than the multiplication operator (*). Therefore, the addition operation is evaluated first, and then the multiplication operation is evaluated.

In the second expression, the multiplication operation has higher precedence than the addition operation. Therefore, the multiplication operation is evaluated first, and then the addition operation is evaluated.

By understanding operator precedence, you can write more concise and efficient C++ code.

Basic Arithmetic & Casting

Basic Arithmetic in C++

C++ provides a number of operators for performing basic arithmetic operations. These operators include:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulo (remainder)

These operators can be used to perform arithmetic operations on variables of different data types. For example, the following code performs arithmetic operations on variables of type int and float:

int a = 10;
float b = 3.14159;

// Add two integers.
int c = a + 5;

// Multiply two floats.
float d = b * 2;

// Divide two integers.
float e = a / 2;

// Calculate the remainder of a division operation.
int f = a % 2;

The results of these operations are stored in the corresponding variables.

Casting in C++

Casting is a way to convert a value from one data type to another. This can be useful when you need to perform arithmetic operations on values of different data types.

There are two types of casting in C++:

  • Implicit casting: Implicit casting occurs when the compiler automatically converts a value from one data type to another. For example, the following code implicitly converts the value of the variable a from type int to type float before performing the multiplication operation:

 

int a = 10;
float b = 3.14159;

// Multiply an int and a float.
float c = a * b;
  • Explicit casting: Explicit casting is when the programmer explicitly converts a value from one data type to another. This can be done using the cast operators (static_castreinterpret_castconst_cast, and dynamic_cast). For example, the following code explicitly converts the value of the variable b from type float to type int before performing the division operation:

 

int a = 10;
float b = 3.14159;

// Divide a float by an int.
int c = static_cast<int>(b) / a;

Explicit casting is often used to prevent errors that can occur when implicitly casting values.

Example

Here is an example of how to use casting in C++:

// Convert a string to an integer.
int a = static_cast<int>("10");

// Convert a floating-point number to a character.
char b = static_cast<char>(3.14159);

// Convert a pointer to an integer to a pointer to a float.
float *c = reinterpret_cast<float*>(pInt);

// Convert a const object to a non-const object.
int *d = const_cast<int*>(pInt);

Casting can be a powerful tool for converting values between different data types. However, it is important to use it carefully to avoid errors.

Prefix and Postfix & Compound assignment

Prefix and postfix operators in C++

Prefix and postfix operators are used to modify the value of a variable. The prefix operator is used before the variable, while the postfix operator is used after the variable.

The following table shows some of the most common prefix and postfix operators in C++:

Operator Prefix Postfix
++ Increments the value of the variable by 1. Increments the value of the variable by 1, and returns the original value.
Decrements the value of the variable by 1. Decrements the value of the variable by 1, and returns the original value.

Example

The following code shows how to use the prefix and postfix operators to increment the value of a variable:

int a = 10;

// Increment the value of a by 1 using the prefix operator.
a++;

// Increment the value of a by 1 using the postfix operator.
int b = a++

// Print the values of a and b.
std::cout << a << " " << b << std::endl;

Output:

12 11

Compound assignment operators in C++

Compound assignment operators combine arithmetic operations with assignment operations. This makes it possible to modify the value of a variable in a single statement.

The following table shows some of the most common compound assignment operators in C++:

Operator Description Example
+= Adds the operand to the left operand x += 5; is equivalent to x = x + 5;
-= Subtracts the operand from the left operand y -= 3; is equivalent to y = y - 3;
*= Multiplies the operand with the left operand z *= 2; is equivalent to z = z * 2;
/= Divides the left operand by the operand a /= 4; is equivalent to a = a / 4;
%= Computes the modulo of the left operand and the operand b %= 7; is equivalent to b = b % 7;
&= Performs a bitwise AND operation on the left operand and the operand c &= 6; is equivalent to c = c & 6;
^= Performs a bitwise XOR operation on the left operand and the operand e ^= 8; is equivalent to e = e ^ 8;
<<= Shifts the left operand left by the number of bits specified by the operand f <<= 3; is equivalent to f = f << 3;
>>= Shifts the left operand right by the number of bits specified by the operand g >>= 2; is equivalent to g = g >> 2;

Example

The following code shows how to use compound assignment operators to modify the value of a variable:

int a = 10;

// Increment the value of a by 1 using the compound assignment operator.
a += 1;

// Print the value of a.
std::cout << a << std::endl;

Output:

11

Compound assignment operators can be a powerful tool for writing concise and efficient C++ code.

Variable Scope (Local vs Global)

Variable scope is a concept in programming that determines where a variable can be accessed from in a program. There are two types of variable scope in C++: local and global.

  • Local variables: Local variables are declared within a function or block of code. They can only be accessed from within the function or block of code in which they are declared.
  • Global variables: Global variables are declared outside of any function or block of code. They can be accessed from anywhere in the program.

Example of local variable scope:

int main() {
  int local_variable = 10;

  // local_variable can only be accessed from within this function.
  std::cout << local_variable << std::endl;

  // This code will cause an error because local_variable is not accessible here.
  std::cout << global_variable << std::endl;

  return 0;
}

Example of global variable scope:

int global_variable = 20;

int main() {
  // global_variable can be accessed from anywhere in the program.
  std::cout << global_variable << std::endl;

  // This code is also valid.
  int local_variable = global_variable;

  return 0;
}

It is important to be aware of variable scope when writing C++ code. Otherwise, you may accidentally access a variable that is not defined or that you are not supposed to access.

Here are some general rules for variable scope in C++:

  • Local variables are scoped to the function or block of code in which they are declared.
  • Global variables are scoped to the entire program.
  • Variables declared in a function can shadow variables declared in the global scope.
  • Variables declared in a block of code can shadow variables declared in the function scope.

By understanding variable scope, you can write more efficient and reliable C++ code.

Selection Statement - if Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

In this section will know more about if statement.

Logical Operators

Logical operators in C++ are used to combine or modify Boolean expressions. They allow you to create more complex conditional statements.

The three logical operators in C++ are:

  • And (&&): Returns true if both of its operands are true. Otherwise, it returns false.
  • Or (||): Returns true if either of its operands is true. Otherwise, it returns false.
  • Not (!): Negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.

Logical operators can be used to create more complex conditional statements. For example, the following code uses the && operator to check if a digit is in a specific range of numbers or not:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cout << "Enter a number";
    cin >> x;
    if (x >= 1 && x <= 100)
        cout << "Ok" << endl;
    else
        cout << "Out of range" << endl;

    return 0;
}

Another Example:

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    cout << "Enter your age";
    cin >> a;
    char g = '\0';
    cout << "Enter your gender";
    cin >> g;
    
    if (a < 18 && g == 'm')
        cout << "male, " << "young boy" << endl;
    else if (a >= 18 && g == 'm')
        cout << "male," << "grown up man" << endl;
    else if (a < 18 && g == 'f')
        cout << "female," << "young girl" << endl;
    else
        cout << "female," << "grown up girl" << endl;
    
    return 0;
}

Note : \0 in C++ is a null character. It is a character with all bits set to zero. It is used to mark the end of a string in C++.

The following code uses the || operator to check if a number is greater than 10 or less than 5:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (number > 10 || number < 5) 
        cout << "The number is greater than 10 or less than 5." << endl;
    
    return 0;
}

The following code uses the ! operator to negate the value of the Boolean expression number > 10:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (! (number > 10)) 
        cout << "The number is not greater than 10." << endl;
    
    return 0;
}

Logical operators can be used to create very complex conditional statements. However, it is important to use them carefully to avoid making your code difficult to read and maintain.

Here are some general rules for using logical operators:

  • Logical operators can be used to combine Boolean expressions to create more complex conditional statements.
  • The && operator returns true if both of its operands are true. Otherwise, it returns false.
  • The || operator returns true if either of its operands is true. Otherwise, it returns false.
  • The ! operator negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.
  • Logical operators can be used in nested expressions.

By understanding how to use logical operators, you can write more efficient and reliable C++ code.

Selection Statement – Switch Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

We explained “if statement” in “Selection Statement – if Statement” section, and now we are going to explain more about “switch statement”.

The switch statement in C++ is a control statement that allows you to execute different blocks of code based on the value of an expression. The general syntax of a switch statement is as follows:

switch (expression) {
  case value1:
    // code to execute if expression equals value1
  case value2:
    // code to execute if expression equals value2
  ...
  default:
    // code to execute if expression does not equal any of the values in the case statements
}

The expression can be any integer expression. The switch statement evaluates the expression and compares it to the values of the case statements. If the expression equals one of the values in the case statements, the code block inside that case statement is executed. If the expression does not equal any of the values in the case statements, the code block inside the default statement is executed.

Here is an example of a switch statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    
    switch (x)
    {
        case 1: cout << "case #1" << endl;
            break;
        case 2: cout << "case #2" << endl;
            break;
        case 3: cout << "case #3" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

You can also use characters instead of numbers in switch statement. For Example:

#include <iostream>

using namespace std;

int main()
{
    char c = 'a';
    
    switch (c)
    {
        case 'a': cout << "case #a" << endl;
            break;
        case 'b': cout << "case #b" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

Output will be:

case #a

Remember!
Using a capital letter like ‘A’ in the previous example is not like using a small letter like ‘a’. They are not the same!

Benefits of using switch statements

Switch statements can be more efficient than using a series of if statements, especially when there are many different cases. Switch statements can also make your code more readable and maintainable.

Conclusion

Switch statements are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Repetition Statement

A repetition statement in C++ is a control statement that allows you to execute a block of code repeatedly until a certain condition is met. There are three types of repetition statements in C++:

  • while loop: The while loop executes a block of code repeatedly while a condition is true.
  • do-while loop: The do-while loop executes a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again.
  • for loop: The for loop executes a block of code a fixed number of times.

Repetition statements are a powerful tool for controlling the flow of your C++ program. They can be used to solve a variety of problems, such as:

  • Iterating over a collection of data
  • Performing a task a certain number of times
  • Waiting for a certain event to occur

Examples of loop break vs continue

break and continue are two flow control statements in C++ that can be used to alter the normal flow of a loop.

break terminates the loop immediately and unconditionally.

continue skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is an example of how to use continue in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 5)
            continue;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 9, inclusive, except for the number 5. The if statement inside the loop checks if i is equal to 5. If it is, the continue statement skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 5.
  4. If i is equal to 5, the program skips the rest of the current iteration of the loop using the continue statement.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times.

Here is the output of this code:

i = 0
i = 1
i = 2
i = 3
i = 4
i = 6
i = 7
i = 8
i = 9

Here is an example of how to use break in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 4)
            break;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 3, inclusive. The if statement inside the loop checks if i is equal to 4. If it is, the break statement terminates the loop immediately and unconditionally.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 4.
  4. If i is equal to 4, the break statement terminates the loop immediately and unconditionally.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times or until the loop is terminated by the break statement.

In this case, the loop will be terminated by the break statement when i is equal to 4. Therefore, the output of the code will be:

i = 0
i = 1
i = 2
i = 3

Which one to use?

Which one to use depends on what you want to achieve. If you want to terminate the loop immediately, use break. If you want to skip the rest of the current iteration of the loop and continue with the next iteration, use continue.

Here are some general tips for using break and continue:

  • Use break sparingly. Terminating a loop early can make your code more difficult to read and understand.
  • Use continue to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using continue.
  • Use break and continue to make your code more efficient. For example, you can use break to terminate a loop early if you have already found what you are looking for.

Nested Loop

A nested loop is a loop that is contained within another loop. This means that the inner loop will iterate for each iteration of the outer loop.

Here is an example of a nested loop in C++:

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= 6; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

This code is a nested for loop that prints a rectangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates 6 times. This means that the code inside the inner loop will be executed 30 times.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 6. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 6.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

******
******
******
******
******

Nested loops can be used to solve a variety of problems. For example, you could use nested loops to iterate over all the elements of a two-dimensional array, or to generate all the possible combinations of two sets of values.

Here are some tips for using nested loops:

  • Use nested loops sparingly. Nested loops can make your code more difficult to read and understand.
  • Use nested loops to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using nested loops.
  • Use nested loops to make your code more efficient. For example, you can use nested loops to avoid searching for an element in an array multiple times.

Draw shapes (Triangle)

You can use the logic of nested loops to create different shapes, for example a triangle.

This code is a nested for loop that prints a triangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

*
**
***
****
*****

What if we want to draw this triangle upside down?

We change the condition in our outer for loop.

This code is a nested for loop that prints an inverted triangle of asterisks to the console. The outer loop iterates from 5 to 1, inclusive, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 5 and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is greater than or equal to 1. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then decrements i by 1.
  9. The outer for loop repeats steps 3-8 until i is less than 1.

Here is the output of the code:

*****
****
***
**
*

Can we make it harder?

This code prints a right triangle of asterisks to the console. The outer loop iterates from 1 to 5, inclusive, and the inner loop iterates from 4 to i, inclusive, where i is the current iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares three variables ij, and k, and initializes them to 1, 4, and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is greater than or equal to i. If it is, the program prints a space to the console.
  5. The inner for loop then decrements j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is less than i.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments i by 1.
  10. The outer for loop repeats steps 3-9 until i is greater than 5.

Here is the output of the code:

    *
   **
  ***
 ****
*****

Let’s print it upside down!

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Look what we have here as an output!

*****
 ****
  ***
   **
    *

Let’s draw a different triangle

#include <iostream>

using namespace std;

int main()
{
    int e = 1;
    for (int a = 1; a <= 5; a++)
    {
        for (int b = 4; b >= a; b--)
        {
            cout << " ";
        }
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e + 2;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares four variables ea, c, and b, and initializes them to 1, 1, 0 and 4, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if a is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if b is greater than or equal to a. If it is, the program prints a space to the console.
  5. The inner for loop then decrements b by 1.
  6. The inner for loop repeats steps 4 and 5 until b is less than a.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments a by 1.
  10. The outer for loop repeats steps 3-9 until a is greater than 5.

Here is the output of the code:

    *
   ***
  *****
 *******
*********

Let’s make it upside down:

#include <iostream>

using namespace std;

int main()
{
    int e = 9;
    for (int r = 1; r <= 5; r++)
    {
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e - 2;
        for (int s = 0; s < r; s++)
        {
            cout << " ";
        }
    }

    return 0;
}

Output:

*********
 *******
  *****
   ***
    *

You can also use nested loops to draw other shapes, such as squares, rectangles, and diamonds.

Draw shapes (square), Draw any Letter Ex:( X,Z,N,E,F)

Nested loops in C++ are a powerful tool for drawing different shapes to the console. By using nested loops, we can iterate over multiple dimensions and print different characters to create different patterns.

Example 1:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == 1 || i == 10)
                cout << "*";
            else if (j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

This code prints a hollow square of asterisks to the console. The outer for loop iterates from 1 to 10, inclusive, and the inner for loop iterates from 1 to 10, inclusive.

The if statement inside the inner for loop checks if i is equal to 1 or 10, or if j is equal to 1 or 10. If any of these conditions are met, the program prints an asterisk to the console. Otherwise, the program prints a space to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 10. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 10. If it is, the program prints an asterisk to the console if i is equal to 1 or 10, or if j is equal to 1 or 10. Otherwise, the program prints a space to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 10.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 10.

Here is the output of the code:

**********
*        *
*        *
*        *
*        *
*        *
*        *
*        *
*        *
**********

Example 2:

If we want to print a letter like X to the console, expecting an output like this:

*   *
 * * 
  *  
 * * 
*   *

We need to set our logic.
To understand how we can put the asterisks in the previous shape, let’s present them this way:

/*
 1 2 3 4 5
1* * * * *
2* * * * *
3* * * * *
4* * * * *
5* * * * *
*/

Now let’s think about it looking at this shape, when the column meets the row we get a star, so we need a loop that goes through all the meeting points between every row and column and we need an if condition to specify our exact locations to make two diagonal lines cross forming our X letter shape.

all of this is represented in the following code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (i == j || j == 6-i)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Example 3:

By understanding how we asterisks are lined here:

/*
 1 2 3 4 5 
1* * * * * 
2* * * * * 
3* * * * * 
4* * * * * 
5* * * * * 
*/

We can think of multiple ways to manipulate our code producing different letters and shapes..

Look at this code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (j == (6) - i || i == 1 || i == 5)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Guess what this shape is?!

Output:

*****
   *
  *  
 *   
*****

Example 4:

Now let’s make our shape more complicated

**********
**      **
* *    * *
*  *  *  *
*   **   *
*   **   *
*  *  *  *
* *    * *
**      **
**********

Applying this code which is no different than previous examples

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == j || j == 11 - i || i == 1 || i == 10 || j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

 

Function Part 1

A function in C++ is a block of code that performs a specific task. Functions can be used to encapsulate common operations, making your code more reusable and easier to understand. Functions can also be used to improve the performance of your code by avoiding duplicate code.

To create a function in C++, you use the following syntax:

return_type function_name(parameter_list) {
  // Function body
}

The return_type specifies the type of data that the function will return. The function_name is the name of the function. The parameter_list is a list of parameters that the function will accept. The function_body is the code that the function will execute.

Here is an example of a simple function in C++:

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}

This function takes two integer parameters, x and y, and returns the sum of those two parameters.

To call a function, you simply use its name followed by a pair of parentheses. For example, to call the sum() function, you would write:

int s = sum(10, 20);

This would assign the value 30 to the variable s.

The code could be written this way:

#include <iostream>

using namespace std;

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}
int main()
{
    int s = 0;
    s = sum(10, 20);
    cout << "sum = " << s << endl;
    
    return 0;
}

The following example takes two float parameters and return the sum of them:

#include <iostream>

using namespace std;

float sum(float x, float y)
{
    float s = 0;
    s = x + y;
    return s;
}
int main()
{
    float s = 0;
    s = sum(20.5, 30.6);
    cout << "sum = " << s << endl;
    
    return 0;
}

Output:

sum = 51.1

The importance of using return:

We need to write a return in a function in C++ to specify the value that the function will return to the calling function. This is important because it allows us to use the function to perform calculations and then use the result of those calculations in our code.

Without the return statement, the function would not be able to return any value to the calling function. This would mean that we would not be able to use the function to perform calculations and then use the result of those calculations in our code.

By using the return statement, we can terminate the execution of the function early and avoid the error. This makes our code more robust and reliable.

Overall, the return statement is an important part of C++ programming. It allows us to return values from functions and to terminate the execution of functions early. This makes our code more reusable, efficient, and reliable.

But can we write a function without using return?

See this example:

#include <iostream>

using namespace std;

void print()
{
    cout << "myName" << endl;
}

int main()
{
    print();
    
    return 0;
}

This code defines a function called print() and a main function. The print() function simply prints the string “myName” to the console. The main function calls the print() function and then returns 0.

The print() function is declared with the void return type. This means that the function does not return any value. We use the void return type when we want a function to perform an action but not return any value.

When you run this code, the following output will be printed to the console:

myName

We use the void return type for the print() function because we only want it to print the string “myName” to the console. We do not need the function to return any value.

 

Functions can also be nested, meaning that one function can call another function. This can be useful for breaking down complex tasks into smaller, more manageable functions.

Functions are a powerful tool in C++ and can be used to improve the quality and performance of your code.

Here are some tips for using functions in C++:

  • Give your functions meaningful names. This will make your code more readable and easier to maintain.
  • Use functions to encapsulate common operations. This will make your code more reusable and easier to understand.
  • Use functions to improve the performance of your code by avoiding duplicate code.
  • Use functions to break down complex tasks into smaller, more manageable functions.

Function Part 2

Example 1:

#include <iostream>

using namespace std;

double avg(int m1, int m2, int m3) 
{
    return double(m1 + m2 + m3) / 3;
}

int main()
{
    int mm1, mm2, mm3;
    cout << "Enter your marks" << endl;
    cin >> mm1 >> mm2 >> mm3;
    cout << "avg = " << avg(mm1, mm2, mm3) << endl;
    
    return 0;
}

This code defines a function called avg(), which takes three integer parameters (m1, m2, and m3) and returns the average of those three parameters as a double value.

The function works by first converting the integer parameters to double values using the double() function. This is necessary because the average of three integers is a fractional number, and we want the function to return a double value.

Next, the function calculates the sum of the three parameters and divides that sum by 3. This gives us the average of the three parameters.

Finally, the function returns the average value.

The program works as follows:

  1. The program declares three integer variables mm1mm2, and mm3 to store the marks entered by the user.
  2. The program prompts the user to enter their marks and reads the marks into the three variables.
  3. The program calls the avg() function to calculate the average of the three marks.
  4. The program prints the average to the console.

Example 2:

#include <iostream>

using namespace std;

int max(int n1, int n2, int n3) 
{
    int mx = n1;
    if (mx < n2)
        mx = n2;
    if (mx < n3)
        mx = n3;
    return mx;
}

int min(int n1, int n2, int n3) 
{
    int mn = n1;
    if (mn > n2)
        mn = n2;
    if (mn > n3)
        mn = n3;
    return mn;
}

int main()
{
    cout << "max = " << max(100, 200, 300) << endl;
    cout << "min = " << min(100, 200, 300) << endl;
    
    return 0;
}

This code defines two functions called max() and min()which both take three integer parameters (n1, n2, and n3) and returns the largest and the smallest of those three parameters.

The first function works by first initializing a variable called mx to the value of the first parameter, n1. Then, the function checks if mx is less than the second parameter, n2. If it is, the function assigns the value of n2 to mx. Next, the function checks if mx is less than the third parameter, n3. If it is, the function assigns the value of n3 to mx. Finally, the function returns the value of mx, which is the largest of the three parameters.

The second function works by first initializing a variable called mn to the value of the first parameter, n1. Then, the function checks if mn is greater than the second parameter, n2. If it is, the function assigns the value of n2 to mn. Next, the function checks if mn is greater than the third parameter, n3. If it is, the function assigns the value of n3 to mn. Finally, the function returns the value of mn, which is the smallest of the three parameters.

Here is the output of the program:

min = 100
max = 300

There are two ways to define a function in a C++ program:

  1. Function declaration: This is a prototype of the function that tells the compiler about the function’s name, return type, and parameters. The function declaration must be placed before the first call to the function.
  2. Function definition: This is the actual code that implements the function. The function definition can be placed anywhere in the program, but it is generally placed at the end of the program.

For example, here is a function declaration and definition:

// Function declaration
int add(int a, int b);

// Function definition
int add(int a, int b) {
  return a + b;
}

The function declaration tells the compiler that there is a function called add() that takes two integer parameters and returns an integer value. The function definition provides the actual code that implements the function.

You can also arrange function declarations and definitions in different ways in your code. For example, you can:

  • Declare all of your functions at the beginning of your program and then define them at the end of your program.
  • Declare and define your functions in the order that they are called in your program.
  • Declare your functions in a header file and define them in a source file.

The best arrangement for your code will depend on the specific needs of your program.

Here is an example of how to use function declarations and definitions in a C++ program:

// Function declaration
int add(int a, int b);

int main() {
  // Function call
  int sum = add(1, 2);

  // Print the sum
  cout << "The sum is: " << sum << endl;

  return 0;
}

// Function definition
int add(int a, int b) {
  return a + b;
}

Of course you should pay a massive attention to the sequential arrangement of your program.

The sequential arrangement of functions in a C++ program is important for two main reasons:

  • Readability: A well-organized program is easier to read and understand. By arranging functions in a logical order, you can make it easier for other programmers to follow the flow of your code.
  • Maintainability: A well-maintained program is easier to update and fix bugs in. By arranging functions in a logical order, you can make it easier to find and fix problems in your code.

Note !

The main function is the entry point for all C++ programs. It is the first function that is called when the program is executed. The main function is responsible for initializing the program, calling other functions, and returning a value to the operating system.

The main function is important for several reasons:

  • It is the starting point for the program execution.
  • It is responsible for initializing the program.
  • It controls the flow of the program by calling other functions.
  • It returns a value to the operating system when the program terminates.

Without the main function, the program would not be able to start executing.

Here is an example of a simple main function in C++:

int main() {
  // Initialize the program
  // ...

  // Call other functions
  // ...

  // Return a value to the operating system
  return 0;
}

This main function initializes the program, calls other functions, and returns a value of 0 to the operating system.

You can use the main function to control the flow of your program by calling other functions. For example, you could write a function to calculate the sum of two numbers and then call that function from the main function.

You can also use the main function to return a value to the operating system. This value is used to indicate whether the program terminated successfully or not.

The main function is a very important part of any C++ program. It is the starting point for the program execution, and it controls the flow of the program.

Example 3:

#include <iostream>

using namespace std;

int avg(int x, int y, int z)
{
    return (x + y + z) / 3;
}

void print()
{
    cout << "Hello" << endl;
}

void xy()
{
    cout << 5 * 10 << endl;
}

int main()
{
    cout << "Nothing" << endl;
    return 0;
}

int f2()
{
    return 5;
}

This code defines four functions: avg(), print(), xy(), and f2(). The avg() function takes three integer parameters and returns the average of those three parameters. The print() function prints the string “Hello” to the console. The xy() function prints the product of 5 and 10 to the console. The f2() function returns the integer 5.

The main function in the code simply prints the string “Nothing” to the console and then returns 0.

When you run this code, the following output will be printed to the console:

Nothing

This is because the only function that is called from the main function is the cout << "Nothing" << endl; statement.

You can use the other functions in the code by calling them from the main function or from other functions.

Function part 3 (built in functions)

Built-in functions in C++ are functions that are provided by the compiler and are available to use in any C++ program. These functions are typically used for common tasks such as input/output, mathematical operations, and string manipulation.

Here are some of the most common built-in functions in C++:

  • Mathematical functions:
    • abs(): Returns the absolute value of a number.
    • sqrt(): Calculates the square root of a number.
    • pow(): Raises a number to a power.
    • sin(): Calculates the sine of an angle in radians.
    • cos(): Calculates the cosine of an angle in radians.
    • tan(): Calculates the tangent of an angle in radians.
    • floor(): Returns the greatest integer less than or equal to a number.
    • ceil(): Returns the smallest integer greater than or equal to a number.
  • String manipulation functions:
    • strlen(): Returns the length of a string.
    • strcpy(): Copies one string to another string.
    • strcat(): Concatenates two strings.
    • strcmp(): Compares two strings and returns an integer value indicating whether they are equal, less than, or greater than each other.
  • Input/output functions:
    • cin: Reads data from the standard input stream.
    • cout: Writes data to the standard output stream.
    • cerr: Writes data to the standard error stream.
    • fopen(): Opens a file for reading or writing.
    • fclose(): Closes a file.

Example 1:

cout << sqrt(18) << endl;

Output:

4.24264

Example 2:

cout << abs(-18) << endl;

Output:

18

Example 3:

cout << mod(10.5,2) << endl;

Output:

0.5

Example 4:

cout << floor(10.2) << endl;

Output:

10

Example 5:

cout << floor(-10.2) << endl;

Output:

-11

Example 6:

cout << ceil(10.2) << endl;

Output:

11

Example 7:

#include <iostream>

using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

To use a built-in function, you simply need to include the appropriate header file. So you might have a problem executing this program. you would need to include the <cmath> header file.

The <cmath> header file contains declarations for a number of mathematical functions, such as sqrt(), pow(), sin(), cos(), and tan(). These functions are useful for performing common mathematical operations, such as calculating the square root of a number, raising a number to a power

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

Output:

3

Example 8:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(10,5) << endl;

    return 0;
}

You would need to include the <algorithm> header file to use any of the algorithms provided by the C++ standard library. These algorithms include sorting, searching, merging, and many more.

Output:

10

Example 9:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(15,max(10,5)) << endl;

    return 0;
}

Output:

15

Example 10:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    
    int x = 0, y = 10;
    swap(x,y);
    cout << "x= " << x << "y= " << y << endl;

    return 0;
}

Output:

x= 10y= 0

Built-in functions can be a very useful tool for C++ programmers. By using built-in functions, you can avoid having to write your own code for common tasks.

 

 

Function part 4 (Random functions)

Random functions in C++ are used to generate random numbers. There are two built-in random functions in C++: rand() and srand().

The rand() function generates a random integer between 0 and RAND_MAX, where RAND_MAX is a macro that is defined in the cstdlib header file. The srand() function is used to seed the random number generator. If you don’t call srand(), the random number generator will be seeded with a default value.

Example 1:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    
    cout << rand() << endl;
    
    return 0;
}

This code prints a random integer to the console.

Example 2:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand() << endl;
    }
    
    return 0;
}

This code is a for loop that prints 10 random integers to the console.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand()%10 << endl;
    }
    
    return 0;
}

This code generates a random number between 0 and 9 and prints it to the console. The modulus operator (%) returns the remainder of a division operation. So, the expression rand()%10 will return the remainder of the operation rand() / 10. This will give us a number between 0 and 9.

Example 4:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

This code generates a random number between 20 and 30 and prints it to the console.

Example 5:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(time(0));
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

The srand(time(0)); function seeds the random number generator with the current time. This ensures that the random numbers are different each time the program is run.

The srand() function takes an integer seed as its argument and initializes the random number generator with that seed. The time(0) function returns the current time as a time_t value, which is an integer.

By seeding the random number generator with the current time, we are using a value that is constantly changing, which ensures that the random numbers are different each time the program is run.

It is important to seed the random number generator before using the rand() function. If you do not seed the random number generator, it will be seeded with a default value, which will result in the same sequence of random numbers being generated each time the program is run.

Example 6:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    int x, y;
    x = time(0);
    for (size_t i = 0; i < 10000; i++)
    {
        cout << time(NULL) << endl;
        y = time (0);
    }
    cout << "The token time:" << y - x << endl;
    return 0;
}

This code prints the current time 10000 times to the console and then prints the total time it took to do so.

The program works as follows:

  1. The int x, y; declaration creates two integer variables, x and y.
  2. The x = time(0); statement assigns the current time to the variable x.
  3. The for (size_t i = 0; i < 10000; i++) loop iterates 10000 times.
  4. On each iteration of the for loop, the following code is executed:
    • The current time is printed to the console using the cout << time(NULL) << endl; statement.
  5. The y = time(0); statement assigns the current time to the variable y.
  6. The cout << "The token time:" << y - x << endl; statement prints the total time it took to print the current time 10000 times to the console.

The time(NULL) function is a synonym for the time(0) function.

You can use this code to measure the performance of your code or to calculate the elapsed time between two events.

Function part 5 (Call By Reference vs Call By Value)

Call by value and call by reference are two different ways to pass arguments to functions in C++.

Call by value is the default passing mechanism in C++. When a function is called by value, a copy of the actual argument is passed to the function. The function then operates on this copy, and any changes made to the copy inside the function will not be reflected in the actual argument outside the function.

Call by reference allows you to pass the reference of the actual argument to the function. This means that the function operates directly on the actual argument outside the function. Any changes made to the argument inside the function will be reflected in the actual argument outside the function.

To pass an argument by reference, you need to use the & operator before the argument name

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void swap(int x, int y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 10 y= 20

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void swap(int&x, int&y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 20 y= 10

As you can see, the result of calling the swap() function is different depending on whether it is called by value or by reference.

Call by reference is often used to modify the values of the arguments outside the function. For example, the swap() function could be used to swap the values of two variables.

Call by reference can also be used to pass large objects to functions without having to copy them. This can improve the performance of your program.

However, it is important to use call by reference carefully, as it can lead to unexpected results if not used correctly. For example, if you pass a reference to a local variable to a function, and the function returns, the local variable will go out of scope, but the reference to it will still be valid. This can lead to a program crash if you try to access the local variable through the reference.

In general, it is best to use call by value unless you have a specific reason to use call by reference.

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void fun(int x, int y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 50 R= 10

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void fun(int&x, int&y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 51 R= 12

As you can see, the result of calling the fun() function is different depending on whether it is called by value or by reference.

Function part 6 (Recursion 1)

Recursion is a programming technique where a function calls itself directly or indirectly. This can be used to solve problems that can be broken down into smaller, simpler problems of the same type.

Recursion can be a bit difficult to understand at first, but it is a powerful tool that can be used to solve a wide variety of problems.

Here is a simple example of a recursive function in C++:

#include <iostream>
using namespace std;
void f(int n)
{
    if (n < 1)
        return;
    else
        cout << "round:" << n << endl;
    f(n - 1);
}

int main()
{
    f(5);
    return 0;
}

The function f(int n) is a recursive function that prints the string “round:” followed by the integer n to the console n times.

The function works by recursively calling itself to print the string “round:” followed by the integer n - 1 to the console. This process continues until n is equal to 1, at which point the function returns.

Output:

round: 5
round: 4
round: 3
round: 2
round: 1

Recursive functions can be a bit difficult to understand at first, but they are a powerful tool that can be used to solve a wide variety of problems.

You should pay attention to these 3 contents of a recursive function (base case, logic and subproblem), which are marked in the following function:

void f(int n)
{
    if (n < 1)
        return; //base case
    else
        cout << "round:" << n << endl; //logic
    f(n - 1); //subproblem
}

The three contents of a recursive function are:

  • Base case: The base case is a special case that is handled directly in the function without making any recursive calls. The base case is usually a simple case that can be solved directly.
  • Logic: The logic of a recursive function is the code that is executed to break down the problem into smaller, simpler problems of the same type. The logic usually involves making recursive calls to the function with smaller input values.
  • Subproblem: A subproblem is a smaller, simpler problem of the same type as the original problem. Recursive functions work by breaking down the original problem into subproblems and then solving the subproblems using the same recursive function.

Here is an example of a recursive function in C++ that calculates the factorial of a number:

#include <iostream>
using namespace std;
int fact(int n)
{
    if (n == 0 || n == 1)
        return 1;
    else
        return n*fact(n - 1);
}

int main()
{
    cout << fact(5) << endl;
    return 0;
}

The function fact(int n) is a recursive function that calculates the factorial of a number. The factorial of a number is the product of all the positive integers less than or equal to that number. For example, the factorial of 5 is 120, because 120 is the product of 1, 2, 3, 4, and 5. So, the  output of our program will be 120.

The function fact(int n) works by recursively calling itself to calculate the factorial of the number one less than the input number. For example, to calculate the factorial of 5, the function would first call itself to calculate the factorial of 4. This would then call itself to calculate the factorial of 3, and so on. Eventually, the function would reach the base case, where the input number is 0 or 1. The base case is a special case that is handled directly in the function without making any recursive calls. The factorial of 0 is 1 and the factorial of 1 is also 1, so the function simply returns 1 in these cases.

Fibonacci Series

The Fibonacci sequence is a series of numbers where each number is the sum of the two previous numbers. The first two numbers in the sequence are 0 and 1, and each subsequent number is the sum of the previous two numbers.

Here is the Fibonacci sequence up to the first 10 numbers:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The Fibonacci sequence can be generated using the following recurrence relation:

F(n) = F(n - 1) + F(n - 2)

where F(n) is the nth number in the Fibonacci sequence.

The Fibonacci sequence has a number of interesting properties. For example, the ratio of successive Fibonacci numbers approaches the golden ratio as the numbers get larger. The golden ratio is an irrational number that is approximately equal to 1.618.

The Fibonacci sequence appears in many different areas of mathematics and nature. For example, it can be used to model the growth of a population of rabbits, the spiral pattern of a seashell, and the branching pattern of a tree.

Here are some examples of how the Fibonacci sequence is used in the real world:

  • Finance: The Fibonacci sequence can be used to identify potential support and resistance levels for stock prices.
  • Music: The Fibonacci sequence can be used to create musical compositions with a pleasing rhythm and structure.
  • Art: The Fibonacci sequence can be used to create works of art with a balanced and harmonious composition.
  • Architecture: The Fibonacci sequence can be used to design buildings and other structures that are aesthetically pleasing and structurally sound.

The Fibonacci sequence is a fascinating and versatile mathematical sequence that has many applications in the real world.

Example:

#include <iostream>
using namespace std;
int fib(int n)
{
    if (n == 0 || n == 1)
        return n;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    cout << fib(3) << endl;
    return 0;
}

The function fib(int n) works by recursively calling itself to calculate the Fibonacci numbers of the previous two numbers. If the input number n is 0 or 1, the function simply returns the number, because the first two Fibonacci numbers are 0 and 1. Otherwise, the function returns the sum of the Fibonacci numbers of the previous two numbers.

Output:

2

 

Function part 7 (Recursion 2)

Example 1:

#include <iostream>
using namespace std;
int sum(int n)
{
    if (n == 1)
        return 1;
    else
        return n + sum(n - 1);
}

int main()
{
    cout << sum(5) << endl;
    return 0;
}

This function calculates the sum of the first n natural numbers. The first n natural numbers are the numbers from 1 to n.

The function works by recursively calling itself to calculate the sum of the first n - 1 natural numbers. If the input number n is 1, the function simply returns the number 1, because the sum of the first natural number is 1. Otherwise, the function returns the sum of the input number n and the sum of the first n - 1 natural numbers.

Output:

15

Example 2:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    if (x == y)
        return x;
    else
        return y + sum(x, y - 1);
}

int main()
{
    cout << sum(4, 6) << endl;
    return 0;
}

This is a recursive function sum. It takes two integer parameters, x and y, which represent the range of numbers to sum. Here’s how the function works:

  • The base case: If x is equal to y, it means we have reached the end of the range, so it returns x. This is the terminating condition for the recursion.
  • The recursive case: If x is not equal to y, it adds the current value of y to the result of calling the sum function again with the same x and y-1. This effectively breaks down the sum of the range into smaller subproblems by reducing the upper bound (y) by 1 in each recursive call.

In the main function, it calls the sum function with the arguments 4 and 6 and then outputs the result to the console using cout. In this case, it will calculate the sum of integers from 4 to 6 (inclusive) and print the result.

When you run this code, it will output the sum of integers from 4 to 6, which is 4 + 5 + 6 = 15. So, the output of this code will be:

15

Function part 8 (Overloading Function)

Function overloading is a feature of C++ that allows you to have two or more functions with the same name, as long as they have different parameters. This can be useful when you want to have a single function that can perform different tasks, depending on the type of data that is passed to it as an argument.

For example, this code is a set of three C++ functions that print different types of data to the console.

#include <iostream>
using namespace std;

void print(int a)
{
    cout << "Integer = " << a << endl;
}
void print(float a)
{
    cout << "Float = " << a << endl;
}
void print(char c)
{
    cout << "Character = " << c << endl;
}

int main()
{
    print(1);
    print('a');
    return 0;
}

The first function, print(int a), takes an integer as an argument and prints it to the console with the prefix “Integer = “.

The second function, print(float a), takes a floating-point number as an argument and prints it to the console with the prefix “Float = “.

The third function, print(char c), takes a character as an argument and prints it to the console with the prefix “Character = “.

Output:

Integer = 1
Character = a

 

Function part 9 (Default arguments)

Default arguments are a feature of C++ that allows you to specify a default value for a function parameter. This means that if a caller of the function does not provide a value for a particular parameter, the default value will be used instead.

Default arguments can be useful for simplifying the code that calls a function, and for making the function more flexible. For example, you could have a function that takes two parameters, but where the second parameter is optional. You could then specify a default value for the second parameter, so that callers of the function do not have to provide a value for it if they do not want to.

Here is an example of how to use default arguments in C++:

#include <iostream>
using namespace std;

int sum(int a = 5, int b = 5, int c = 5)
{
    return a + b + c;
}

int main()
{
    cout << sum(10, 55) << endl;
    return 0;
}

This code calculates the sum of three integers. The program uses default arguments to provide default values for the three integers. This means that if the caller of the sum() function does not provide values for all three integers, the default values will be used instead.

The main() function calls the sum() function with the arguments 10 and 55. The sum() function will then return the sum of the three integers, which is 70. The main() function will then print the result to the console.

Output:

70

Here are some tips for using default arguments:

  • Do not write your default argument in the middle of two arguments like this (int a, int b = 5, int c), it will produce an error to the compiler.
  • Be careful not to overwrite default parameters with values that are not valid for the function.
  • Use default parameters to provide default values for parameters that are not essential to the function’s functionality.

Function part 10 (Inline Function)

An inline function in C++ is a function whose code is substituted at the point of call. This means that the compiler copies the code of the inline function into the calling function, instead of generating a call instruction.

Inline functions are typically used for small functions that are frequently called. This can improve the performance of the program, as it eliminates the overhead of function calls.

To declare an inline function in C++, you use the inline keyword before the function declaration. For example:

#include <iostream>
using namespace std;

inline void p()
{
    cout << "hello" << endl;
}

int main()
{
    p();
    p();
    p();
    return 0;
}

inline void p(), defines an inline function called p(). The function takes no arguments and simply prints the word “hello” to the console, followed by a newline character.

The three lines, p();, p();, and p();, call the p() function three times.

When the program is executed, the following output will be printed to the console:

hello
hello
hello

It is important to note that the compiler is not obligated to inline a function, even if it is declared as inline. The compiler may choose not to inline a function if it is too large or if it is called indirectly.

Here are some of the benefits of using inline functions:

  • Improved performance: Inline functions can improve the performance of a program by eliminating the overhead of function calls.
  • Reduced code size: Inline functions can reduce the code size of a program by removing the need to generate separate code for each function call.
  • Increased readability: Inline functions can make code more readable by eliminating the need to jump back and forth between different functions.

However, there are also some potential drawbacks to using inline functions:

  • Increased compile time: Inlining functions can increase the compile time of a program, as the compiler needs to copy the code of the inline function into each calling function.
  • Increased code size: If an inline function is called frequently, it can increase the code size of the program.
  • Reduced maintainability: Inline functions can make code more difficult to maintain, as the code for the inline function is scattered throughout the program.

Overall, inline functions can be a useful tool for improving the performance and readability of code. However, it is important to use them carefully, as they can also increase the compile time and code size of a program.

Here are some tips for using inline functions effectively:

  • Only inline small functions that are frequently called.
  • Avoid inlining functions that are too large or that are called indirectly.
  • Use the inline keyword consistently, so that the compiler can make informed decisions about whether or not to inline a function.
  • Document your code clearly, so that other developers understand how and why inline functions are being used.

Static variable

A static variable in C++ is a variable that is allocated once and remains in memory throughout the execution of the program. Static variables can be declared at global scope, namespace scope, class scope, or function scope.

Static variables at global scope are initialized when the program starts and are destroyed when the program ends. Static variables at namespace scope are initialized when the namespace is loaded and are destroyed when the namespace is unloaded. Static variables in classes are initialized when the class is first used and are destroyed when the program ends. Static variables in functions are initialized when the function is first called and are destroyed when the function returns.

Static variables can be useful for a variety of purposes, such as:

  • Storing global state information: Static variables can be used to store global state information that needs to be accessed by multiple functions in a program.
  • Implementing singletons: Static variables can be used to implement singletons, which are classes that can only have one instance.
  • Implementing lazy initialization: Static variables can be used to implement lazy initialization, which is a technique for delaying the initialization of a variable until it is first used.

Here is an example of a static variable declared in a function:

#include <iostream>
using namespace std;

void fun()
{
    static int x = 0;
    x++;
    cout << x << endl;
}

int main()
{
    fun();
    fun();
    return 0;
}

This code is a C++ program that defines a function called fun() and then calls it twice from the main() function. The fun() function declares a static variable called x and increments it each time it is called. The function then prints the value of x to the console.

Because x is a static variable, its value is preserved between function calls. This means that when the fun() function is called the second time, the value of x will be 1, not 0. Therefore, the output of the program will be as follows:

1
2

This code demonstrates how static variables can be used to store state information that needs to be accessed by multiple function calls.

Aliasing & Constant Variable

Aliasing

Aliasing in C++ is when two or more different names refer to the same memory location. This can happen when you use pointers or references, or when you declare two variables of the same type and initialize them to the same value.

For example, the following code creates an alias to the variable x:

int x = 1;
int &y = x;

Now, both the variables x and y refer to the same memory location. If you change the value of x, the value of y will also change.

Example:

#include <iostream>
using namespace std;

int main()
{
    int x = 1;
    int &y = x;
    x = 5;
    int &z = y;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = 7;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = x + z - 3;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;

    return 0;
}

The code begins by declaring an integer variable named x and initializing it to 1. Then, it declares an integer reference named y and binds it to the variable x. This means that y is now an alias for x.

Next, the code assigns the value 5 to the variable x. This also changes the value of the variable y, since it is an alias for x.

Then, the code declares another integer reference named z and binds it to the variable y. This means that z is also an alias for x.

Now, all three variables x, y, and z refer to the same memory location. This means that changing the value of any one of these variables will also change the value of the other two variables.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 5 y = 5 z = 5

Next, the code assigns the value 7 to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 7 y = 7 z = 7

Finally, the code calculates the value of x + z - 3 and assigns it to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 11 y = 11 z = 11

This code demonstrates how aliasing can be used to change the values of multiple variables at once. It also demonstrates how aliasing can be used to create aliases for complex expressions.

It is important to note that aliasing can be a powerful tool, but it can also lead to confusion and errors if used incorrectly. It is important to carefully consider the implications of aliasing before using it in your code.

Constant Variable

A constant variable in C++ is a variable whose value cannot be changed after it is initialized. To declare a constant variable, you use the const keyword before the variable type. For example:

const double Pi = 3.14;

Once you have declared a constant variable, you cannot assign a new value to it. If you try to do so, the compiler will generate an error.

Example:

#include <iostream>
using namespace std;

int main()
{
    const double Pi = 3.14;
    int r;
    cout << "please enter r: ";
    cin >> r;
    double a = Pi * r * r;
    cout << "Area of circle = " << a << endl;

    return 0;
}

This code calculates the area of a circle. The program begins by declaring a constant double variable named Pi and initializing it to the value 3.14. Then, it declares an integer variable named r and prompts the user to enter a value for it.

Next, the program calculates the area of the circle using the following formula:

  • Area = πr²

The program then prints the area of the circle to the console.

Here is a breakdown of the code:

int main()
{
  // Declare a constant double variable named Pi and initialize it to the value 3.14.
  const double Pi = 3.14;

  // Declare an integer variable named r.
  int r;

  // Prompt the user to enter a value for r.
  cout << "please enter r: ";
  cin >> r;

  // Calculate the area of the circle.
  double a = Pi * r * r;

  // Print the area of the circle to the console.
  cout << "Area of circle = " << a << endl;

  return 0;
}

Output:

please enter r: 5
Area of circle = 78.5

Aliasing and constant variables can interact in a few interesting ways:

  • If you have a constant variable and you create an alias to it, the alias is also constant. This is because the alias is just another name for the same variable, and the value of the variable cannot be changed.
  • If you have a constant variable and you pass it to a function as a parameter, the function cannot change the value of the variable. This is because the function is only allowed to modify the local copy of the variable.
  • If you have a pointer to a constant variable, you can still use the pointer to dereference the variable and read its value. However, you cannot use the pointer to change the value of the variable.

Here is an example of aliasing and constant variables in C++:

#include <iostream>
using namespace std;

int main()
{
    int i = 1;
    int &j = i;
    cout << "j = " << j << endl;
    const int &k = j;
    cout << "k = " << k << endl;

    return 0;
}

Output:

j = 1
k = 1

 

One Dimensional Array (part 1)

An array is a data structure that stores a collection of elements of the same data type. These elements are stored in contiguous memory locations, and they can be accessed using an index. Arrays provide a way to manage and manipulate a large set of data efficiently.

In C++, you can declare an array by specifying its data type and the number of elements it will hold. Here’s a basic syntax:

data_type array_name[array_size];

Arrays in C++ are zero-indexed, meaning the first element is accessed using the index 0, the second element with index 1, and so on. You can access and modify array elements using square brackets:

array_name[index] = new_value;

Here is an example:

#include <iostream>
using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 20;
    cout << x[0] << endl;
    x[2];
    x[3];
    x[4];

    return 0;
}

1. int x[5];

This line declares an integer array named x with a size of 5. It means that x can store five integer values. However, at this point, the values in the array are uninitialized, which means they contain random data.
2. x[0] = 10;

Here, we assign the value 10 to the first element of the array x. In C++, arrays are zero-indexed, so x[0] refers to the first element.
3. x[1] = 20;

Similarly, we assign the value 20 to the second element of the array x, which is x[1].
4. cout << x[0] << endl;

This line prints the value of the first element of the array x, which is 10, to the console. It uses the cout object from the C++ Standard Library to output the value, followed by an end-of-line character (endl) for formatting.
5. x[2];

These lines appear to be accessing the third element of the array x, but they don’t do anything. It’s essentially a “noop” operation, and the value in x[2] remains uninitialized or unchanged.
6. x[3]; and x[4];

Similar to the previous line, these lines access the fourth and fifth elements of the array x, but they also don’t perform any meaningful operation.

Output:

10

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 5;
    x[4] = x[0] + x[1];
    cout<< x[4] << endl;

    return 0;
}

Output:

15

Arrays only accept constant array size, Example:

#include <iostream>

using namespace std;

int main()
{
    const int t = 5;
    int x[t];

    return 0;
}

This code declares an integer array `x` with a size of 5, and the size is determined by the constant `t`, which is set to 5. The `const` keyword ensures that `t` cannot be changed later in the program. This code doesn’t perform any further operations on the array; it simply demonstrates how to declare an array with a size determined by a constant.

You can also declare the size of your array, and declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = { 1,4,8,7,2 };
    cout << x[0] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes it with the values 1, 4, 8, 7, and 2. It then prints the first element of the array, which is 1, to the console. This code demonstrates how to create an array and access its elements in C++.

But what if you declared no initial values into your array?

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 but does not initialize its elements. Therefore, when you attempt to print the value of the fourth element, it will display a random or garbage value. It’s important to initialize array elements before using them to avoid unpredictable behavior in your programs.

What if you declared only one initial value that equals to 0?

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {0};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes all its elements to 0. It then prints the value of the fourth element of the array, which is 0, to the console. This code demonstrates how to create an array with specific initial values in C++.

You can also declare a size of array and declare some of the first initial values, for example:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {1,2,3};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes the first three elements with values, while the remaining two elements are automatically initialized to 0. It then prints the value of the fourth element, which is 0, to the console.

Or, you can declare no size of your array and only declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[] = {1,2,3,4,5};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x and initializes it with values using an array initialization list. It then prints the value of the fourth element of the array, which is 4, to the console. This code demonstrates how to create an array and access its elements in C++.

How does the compiler store the values on an array?

The compiler stores the values of an array in contiguous memory locations. This means that the values of the array elements are stored next to each other in memory. The compiler allocates a block of memory that is large enough to store all of the array elements, and then it stores the values of the elements in this block of memory.

The compiler keeps track of the address of the first element in the array, and then it uses this address to access the other elements in the array. For example, to access the element at index i, the compiler adds i to the address of the first element.

The specific way that the compiler stores the values of an array depends on the data type of the array elements. For example, if the array elements are integers, the compiler will store each integer in a single memory location. However, if the array elements are structs, the compiler will store each struct in a contiguous block of memory locations.

This code shows you how to read and store user input in an array in C++, it allows the user to input an integer value for the first element of an array, arr[0], and then it displays the value that was entered.

#include <iostream>

using namespace std;

int main()
{
    int arr[50];
    cout << "Enter arr[0]: " << endl;
    cin >> arr[0];
    cout << arr[0] << endl;

    return 0;
}

 

To traverse the elements of an array, you can use loops like for or while. Looping through an array allows you to perform operations on each element systematically.

Example:

#include <iostream>

using namespace std;

int main()
{
    int arr[10];
    for (size_t i = 0; i < 10; i++)
    {
        cout << "Enter arr[" << i << "]: ";
        cin >> arr[i];
    }
    for (size_t i = 0; i < 10; i++)
    {
        cout << "arr[" << i << "] = " << arr[i] << endl;
    }

    return 0;
}

This code allows the user to input 10 integer values, one for each element of the array, and then it displays the values along with their indices. It demonstrates how to read and store multiple user inputs in an array and subsequently print the contents of the array in C++.

One Dimensional Array (part 2)

Arrays are incredibly versatile, and you can perform various operations on them, such as copying the initial values of an existing array into another one.

Of course we cannot use the following command:

arr2 = arr1;

Because we aren’t assigning a single value. Each array has a collection of values, so if we need to assign a single value in an array we have to specify its index:

arr2[0] = arr1[0];

But what if we need to assign all the values of an array into another array?

Example 1:

#include <iostream>

using namespace std;

int main()
{
    const int s = 4;
    int arr1[s] = { 10,20,30,40 };
    int arr2[s];

    for (size_t i = 0; i <= s-1; i++)
    {
        arr2[i] = arr1[i];
    }

    for (size_t i = 0; i < s; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    return 0;
}

This code initializes an array arr1 with values, then copies the contents of arr1 into another array arr2. Finally, it prints the elements of arr2. This demonstrates how to copy the contents of one array into another in C++.

Output:

10 20 30 40

Example 2:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,0 };
    int sum = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        //sum += arr[i];
        sum = sum + arr[i];
    }
    cout << "sum = " << sum << endl;

    return 0;
}

This code calculates the sum of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate values.

Output:

sum = 1000

Example 3:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,100 };
    long long d = 1;
    
    for (size_t i = 0; i < s; i++)
    {
        d *= arr[i];
    }
    cout << "multi = " << d << endl;

    return 0;
}
  • long long d = 1; :This line initializes a long long integer variable d to 1. This variable will be used to accumulate the product of the elements in the array.
  • long long is a data type in C++ that represents a 64-bit integer. It’s designed to store very large integer values. It can hold a wider range of values compared to regular int or long integers.
  • So, the statement long long d = 1; declares a variable named d with a data type of long long and initializes it with the value 1. This variable can then be used to store and manipulate large integer values in your program.

In summary, this code calculates the product of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate the product of its elements.

Output:

multi = 200000000000

Example 4:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,501,101 };
    int sumEven, sumOdd = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] % 2 == 0)
            sumEven += arr[i];
        else
            sumOdd += arr[i];
    }
    cout << "Sum of even numbers = " << sumEven << endl;
    cout << "Sum of odd numbers = " << sumOdd << endl;

    return 0;
}

This code calculates the sum of even and odd numbers separately in the integer array arr and then prints the results to the console.

Output:

Sum of even numbers = 500
Sum of odd numbers = 602

Example 5:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int marks[s] = { 100,99,98,88,70,90 };
    int sum = 0;
    for (size_t i = 0; i < s; i++)
    {
        sum += marks[i];
    }
    cout << "Average = " << sum / s << endl;

    return 0;
}

This code calculates the average of the marks stored in the integer array marks and then prints the average to the console.

Output:

Average = 90

Example 6:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int arr[s] = { 22,100,95,101,200,90 };
    int max = 0;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] > max)
            max = arr[i];
    }
    cout << "Maximum number = " << max << endl;

    return 0;
}

This code finds the maximum value among the numbers stored in the integer array arr and then prints the maximum value to the console.

Output:

Maximum number = 200

Example 7:

#include <iostream>

using namespace std;

int main()
{
    int vector[5];
    cout << "Enter 5 numbers: ";
    for (int i = 0; i < 5; i++)
        cin >> vector[i];
    cout << endl;
    
    int Element;
    cout << "What is the element you are looking for? ";
    cin >> Element;
    
    bool Found = false;
    int i;
    for (i = 0; i < 5; i++)
        if (Element == vector[i])
        {
            Found = true;
            break;
        }
    cout << endl;
    if (Found)
        cout << Element << " found at position " << i << endl;
    else
        cout << Element << " is not in this array!" << endl;

    return 0;
}

In this C++ code, you’re taking user input to populate an integer array `vector` of size 5 and then searching for a specific element within the array. Let’s break down the code step by step:

  1. int vector[5];
    – This line declares an integer array `vector` with a size of 5, which can store up to five integer values.
  2. Input Loop to Populate the Array:
    – The code prompts the user to enter five numbers and stores them in the `vector` array using a `for` loop that iterates five times. Each input is assigned to a different element of the array.
  3. int Element;
    – This line declares an integer variable `Element`, which will store the value the user is searching for.
  4. Prompt for the Element to Search:
    – The code asks the user to input the element they want to search for.
  5. Search Loop:
    – The `for` loop is used to search for the element within the array. If the element is found, the loop breaks, and the `Found` flag is set to `true`. The variable `i` keeps track of the position where the element was found.
  6. Output the Result:
    – The code then checks if the element was found (i.e., `Found` is `true`). If found, it displays the element and its position in the array. If not found, it informs the user that the element is not in the array.

In summary, this code allows the user to enter five numbers into an array and then search for a specific element within the array. It provides feedback on whether the element was found and its position in the array.

One Dimensional Array part 3 (Passing Array To Function)

In C++, you can pass an array to a function, and this is a fundamental concept when working with arrays. When you pass an array to a function, you’re essentially allowing that function to operate on the array’s elements or modify the array if needed.

Here’s an explanation of how to pass an array to a function in C++:

Array Declaration in a Function

Array Parameters: To pass an array to a function, you need to declare the function parameter as an array. You can declare it in two ways:

  • Using a Fixed Size: If you know the size of the array in advance, you can specify the size in the function parameter, like this:
void functionName(int arr[5]) {
    // Code to work with the array
}
  • Using a Pointer: You can also declare the function parameter as a pointer to the array’s elements without specifying the size, like this:
void functionName(int *arr, int size) {
    // Code to work with the array
}

In this case, you pass the size of the array as a separate argument.

Passing the Array to the Function

Calling the Function: When you call the function, you provide the array as an argument. If you declared the function parameter with a fixed size, you pass the array directly. If you used a pointer, you pass the array and its size as arguments.

Example with a fixed-size array parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray);

Example with a pointer parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray, 5);

Using the Array in the Function

Working with the Array: Inside the function, you can access and manipulate the elements of the array as needed. You can use array indices (e.g., arr[0], arr[1]) to access individual elements, and you can use loops to iterate through the elements.

Example of accessing array elements:

void functionName(int arr[5]) {
    for (int i = 0; i < 5; i++) {
        // Access and manipulate arr[i]
    }
}

Here is a demonstration of passing an array to functions for setting values in the array and then printing those values:

#include <iostream>
using namespace std;

void set(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << "Enter array value: ";
        cin >> arr[i];
    }
}

void print(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << arr[i] << " ";
    }
}

int main()
{
    int a[5];
    set(a, 5);
    print(a, 5);

    return 0;
}

The set function allows the user to set values in the array, and the print function prints the values stored in the array. It’s a practical example of how to work with arrays and functions in C++.

Modifying the Array

Example 1:

This code shows an implementation of the “Bubble Sort” algorithm. Bubble Sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, indicating that the list is sorted. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

int main()
{
    int vector[] = {6,5,4,1,2};
    int t = 0;
    
    // Bubble Sort algorithm
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (vector[j] > vector[j + 1])
            {
                t = vector[j];
                vector[j] = vector[j + 1];
                vector[j + 1] = t;   
            }
        }
    }
    
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }

    return 0;
}
  1. int vector[] = {6, 5, 4, 1, 2};:
    An integer array vector is initialized with unsorted values.
  2. int t = 0;:
    An integer variable t is declared to be used for swapping elements during the sorting process.
  3. Bubble Sort Algorithm:
    The nested for loops are used to implement the Bubble Sort algorithm. The outer loop (i) controls the number of passes, and the inner loop (j) compares adjacent elements and swaps them if they are out of order.
  4. If the element at index j is greater than the element at index j + 1, a swap is performed to put them in ascending order.
  5. Printing the Sorted Array:
    After sorting is complete, the code uses a for loop to print the sorted elements in ascending order.

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array. Bubble Sort is not the most efficient sorting algorithm for large data sets, but it’s easy to understand and implement.

Example 2:

This code performs the sorting of an integer array using the Bubble Sort algorithm. It sorts the array in ascending order and then prints the sorted values. Let’s break down the code step by step:

#include <iostream>
using namespace std;

const int s = 5;
void sort(int arr[])
{
    int t = 0;
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;   
            }
        }
    }
}

void print(int vector[])
{
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }
}

int main()
{
    int vector[] = {0,-1,55,-5,-100};
    sort(vector);
    print(vector);
    return 0;
}

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array.

Example 3:

This code demonstrates how to reverse the elements of an integer array using a reversArray function. It reverses the array in-place and then prints the reversed array:

#include <iostream>
using namespace std;

void reversArray(int arr[], int s)
{
    for (size_t i = 0; i < s / 2; i++)
    {
        swap(arr[i], arr[s - i - 1]);
    }
}

int main()
{
    int vector[] = {3,2,4,5,6};
    reversArray(vector, 5);
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << " ";
    }

    return 0;
}

The output of this code will be the reversed array, where the elements are reversed in place. This is achieved by swapping the first element with the last element, the second element with the second-to-last element, and so on. It’s a simple and efficient way to reverse the order of elements in an array.

 

Note:

If you don’t want to modify your array you can initial its value as a constant in the function. Example:

void print(const int arr[], int s)
{
    //body of the function
}

This way any try to modify the array will produce an error.

One Dimensional Array part4 (Array Of Character)

An array of characters in C++ is often referred to as a “string.” It is a fundamental data structure used to store sequences of characters, such as words, sentences, or even individual characters. In C++, strings are represented as arrays of characters, terminated by a special null character, ‘\0’, which indicates the end of the string.

to initiate a character we use a single quotation like this ‘L’.

Example 1:

char ch[5] = { 'a','b','c','d','e','\0' };

The null character (‘\0’), NULL or 0, is used to indicate the end of the string. This character is automatically added to the end of string literals and is crucial for various string manipulation functions.

If you add characters after the null character they won’t be read by the program.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    char ch[5];
    cin >> ch;
    cout << ch << endl;
    return 0;
}

This code reads a sequence of characters into a char array and then prints the array. However, there are a few things to note about potential issues and improvements in the code:

  1. Array Size:
    The char array ch has a size of 5. If you enter more than 4 characters, it will result in a buffer overflow, causing undefined behavior. It’s essential to ensure that the input doesn’t exceed the array size.
  2. Input Method:
    When using cin >> ch, it reads characters until it encounters whitespace. If you want to read an entire line (including spaces), you should use cin.getline(ch, size) or cin.get(ch, size).

Example 3:

#include <iostream>
using namespace std;

int main() {
    char ch[10];

    // Read up to 9 characters into the char array
    cin.get(ch, 10);

    // Output the char array
    cout << ch << endl;

    return 0;
}

This code reads up to 9 characters (plus the null terminator) into a char array using cin.get() and then prints the array.
Here are a few points to note:

  1. Array Size:
    The char array ch has a size of 10. Since cin.get() reads up to one less than the specified size (leaving space for the null terminator), it effectively reads up to 9 characters.
  2. Input Method:
    cin.get(ch, 10) reads characters until either 9 characters are read, the newline character is encountered, or the end of file is reached. It stops reading after reaching the specified number of characters or encountering one of these conditions.
  3. Null Terminator:
    The array is not explicitly null-terminated by cin.get(); however, C++ streams automatically append a null terminator at the end of the string when reading into a character array. Therefore, the array ch is effectively treated as a C-style string.

Output:

The cout << ch << endl; statement prints the contents of the char array, treating it as a null-terminated string. If fewer than 9 characters were entered, it prints the characters entered. If 9 characters were entered, it prints those 9 characters followed by the null terminator.

Input Limitation:

Keep in mind that the user input is limited to 9 characters, and exceeding this limit may lead to unexpected behavior. It’s essential to handle potential input overflows based on the specific requirements of your program.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char ch1[10], ch2[10];
    cin.getline(ch1, 10);
    cin.getline(ch2, 10);
    cout << ch1 << endl;
    cout << ch2 << endl;
    return 0;
}

This code reads two lines of input into separate char arrays and then prints each array on a new line.

Here are some points to note:

  1. Array Size:
    Both ch1 and ch2 are char arrays with a size of 10. The cin.getline() function reads characters until it encounters a newline character or reaches the specified size (leaving space for the null terminator).
  2. Input Limitation:
    The user input for each line is limited to 9 characters, and the null terminator is automatically added by cin.getline().
  3. Handling Spaces:
    Unlike cin >>, cin.getline() reads the entire line, including spaces. This allows you to input strings with spaces.

Output:

The cout << ch1 << endl; statement prints the contents of the first char array, treating it as a null-terminated string.
Similarly, cout << ch2 << endl; prints the contents of the second char array.
Newline Character:

Each call to cin.getline() reads until it encounters a newline character or reaches the specified size. The newline character is consumed but not stored in the arrays.
This code allows you to input two lines of text (up to 9 characters each) and then prints each line on a new line. It’s suitable for reading and displaying multiple lines of text, handling spaces, and avoiding buffer overflow issues.

 

There are some functions that are part of the C Standard Library and are used for manipulating C-style strings, which are arrays of characters. Here’s an explanation of each function:

  • strcpy (String Copy):

Description: The strcpy function is used to copy the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4];
    strcpy_s(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcpy_s Function:
    The strcpy_s function is part of the C Standard Library and is designed to provide safer string copying by including a size check.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes three characters for the content of ch1 (“AAA”) and one additional space for the null terminator (‘\0’).
  3. Safe String Copy:
    Unlike the standard strcpy function, strcpy_s requires you to provide the size of the destination array (destsz). It checks if there is enough space in the destination array to accommodate the source string and the null terminator. If there isn’t enough space, the function does not perform the copy and returns an error code.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2, which should be “AAA” in this case.

By using strcpy_s, you are taking steps to prevent buffer overflow issues that could occur if the destination array is not large enough to hold the contents of the source string. This is a good practice for enhancing the safety and robustness of your code.

  • strcat (String Concatenate):

Description: The strcat function is used to concatenate (append) the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4] = "HH";
    strcat(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcat Function:
    The strcat function is part of the C Standard Library and is used to concatenate the contents of one C-style string to another.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes two characters (“HH”) and one additional space for the null terminator (‘\0’).
  3. Concatenation:
    The strcat(ch2, ch1); line appends the contents of ch1 to the end of ch2. It starts copying characters from the null terminator of ch2 to the end of ch1 until it encounters the null terminator of ch1. The null terminator of ch2 is updated accordingly.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2 after the concatenation. Since the size of ch2 is limited to 4, it can hold “HH” and the null terminator, but only one additional character from ch1 (“A”) can be accommodated.
Result:

The output of this code is “HHA”, which is the result of concatenating “AAA” to the end of the existing content in ch2.
It’s important to ensure that the destination array has enough space to accommodate the concatenated string, and using functions like strcat requires careful management of buffer sizes to prevent buffer overflows.

  • strcmp (String Compare):

Description: The strcmp function is used to compare two C-style strings lexicographically.

The strcmp function returns an integer value indicating the lexicographic relationship between the two strings. It returns:
– 0 if the strings are equal,
– a negative value if str1 is lexicographically less than str2,
– a positive value if str1 is lexicographically greater than str2.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    cout << strcmp("abc", "abc") << endl;
    return 0;
}

Output:

The cout statement outputs the result of the comparison using strcmp. In this case, since the strings are equal, the output will be 0.

The strcmp function is commonly used for sorting strings, dictionary operations, and other scenarios where you need to determine the lexicographic order of strings. It’s important to handle the result appropriately based on your specific requirements in the program.

  • strlen (String Length):

Description: The strlen function is used to determine the length of a C-style string.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch[] = "jjjjjjjjjjjjjjjjjjjjj";
    cout << strlen(ch) << endl;
    return 0;
}

Output:

The cout statement outputs the result of strlen(ch), which is the length of the string “jjjjjjjjjjjjjjjjjjjjj”. Since there are 21 characters in the string, the output will be 21.

The strlen function is useful for obtaining the length of strings, and it’s important to note that the length does not include the null terminator. Make sure that the string is properly null-terminated to get accurate results with strlen.

 

 

 

 

 

Two Dimensional Array

A two-dimensional array in C++ is a structure that allows you to store elements in a tabular form, organized in rows and columns. It is essentially an array of arrays.

Here’s an explanation of a two-dimensional array in C++:

  • Declaration and Initialization:
// Declaration of a 2D array
int matrix[3][4];

// Initialization of a 2D array
int anotherMatrix[2][3] = { {1, 2, 3}, {4, 5, 6} };
  • Structure:

In a 2D array, elements are arranged in rows and columns. The first index represents the row, and the second index represents the column.

  • Memory Representation:

In memory, a 2D array is stored in a contiguous block of memory. The elements of each row are stored together, and rows are stored one after the other.

  • Accessing Elements:
int value = matrix[1][2];  // Accessing the element in the second row and third column
  • Initialization with Nested Loops:

Common Operations:

– Iterating through elements using nested loops.
– Performing operations on each element.
– Passing a 2D array to functions.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int a[3][4];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 4; j++)
        {
            cin >> a[i][j];
        }
    }
    for (size_t r = 0; r < 3; r++)
    {
        for (size_t c = 0; c < 4; c++)
        {
            cout << a[r][c] << " ";
        }
        cout << endl;
    }
    return 0;
}

This code allows the user to input values into a 2D array a[3][4] and then prints the array in a tabular form.

Here are the key points:

  1. 2D Array Input:
    The nested loops (for loops) are used to iterate over each element of the 2D array and input values using cin.
  2. 2D Array Output:
    Another set of nested loops is used to iterate over each element of the 2D array and output the values using cout.
    The inner loop prints each row, and the outer loop moves to the next row, creating a tabular form.
  3. Tabular Output:
    The cout << a[r][c] << ” “; statement prints each element of the 2D array followed by a space.
    The cout << endl; statement is used to move to the next line after printing each row.
  4. User Interaction:
    The user is prompted to input values for each element of the 2D array. The input is expected to be provided in a row-wise fashion.
  5. Array Size:
    The array a is declared with 3 rows and 4 columns, creating a 3×4 matrix.

This code allows the user to interactively input values into a 3×4 2D array and then displays the array in a tabular format.

Example 2:

#include <iostream>
using namespace std;

int main() {
    // Initialization of a 2D array with predefined values
    int arr[2][4] = {{1, 1, 1, 1}, {2, 2, 2, 2}};
    
    // Variable to store the sum of array elements
    int sum = 0;

    // Nested loops to iterate over each element of the 2D array
    for (size_t r = 0; r < 2; r++) {
        for (size_t c = 0; c < 4; c++) {
            // Accumulate the values to calculate the sum
            sum += arr[r][c];
        }
    }

    // Output the sum of array elements
    cout << "sum = " << sum << endl;

    return 0;
}

Output:

In this specific example, the sum is calculated as follows: 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 = 12.
The output will be sum = 12.

This code is a simple illustration of how to iterate over elements in a 2D array and perform a basic operation, in this case, calculating the sum of all elements.

Example 3:

#include <iostream>
using namespace std;
int main()
{
    int marks[10][5];
    for (size_t r = 0; r < 10; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            cout << "Enter mark " << c + 1 << " " << "for student " << r + 1 << ": " << endl;
            cin >> marks[r][c];
        }
    }
    double s = 0;
    float avg[10];
    for (size_t r = 0; r < 10; r++)
    {
        s = 0;
        for (size_t c = 0; c < 5; c++)
        {
            s += marks[r][c];
        }
        avg[r] = s / 5;
        cout << "Average for student #" << r + 1 << " = "<< avg[r] << endl;
    }
    return 0;
}

This code collects marks for 10 students in 5 subjects, calculates the average mark for each student, and then outputs the average for each student.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char MTXchar[5][5] = {{'*','$','$','$','$'},
                          {'$','*','$','$','$'},
                          {'$','$','*','$','$'},
                          {'$','$','$','*','$'},
                          {'$','$','$','$','*'}};
                          
    for (size_t r = 0; r < 5; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            
            if (c == r)
                cout << MTXchar[r][c];
            else
                cout << " ";
        }
        cout << endl;
    }
    return 0;
}

This code defines a 5×5 matrix (MTXchar) containing ” characters on the main diagonal and ‘$’ characters elsewhere. It then prints only the characters on the main diagonal, resulting in a diagonal line of ” characters.

Output:

The code outputs a diagonal line of ‘*’ characters on the console.

*    
 *   
  *  
   * 
    *

 

Passing a two-dimensional array to a function in C++ involves specifying the array as a parameter in the function declaration. Since a 2D array is essentially an array of arrays, you need to specify the size of the columns (since the rows are implicitly known based on the number of arrays).

  • Function Declaration:

When declaring a function that accepts a 2D array, you need to specify the array parameter along with the size of the columns. The size of the rows is not explicitly specified.

void functionName(int arr[][COLS], size_t rows, size_t cols) {
    // Function logic using arr
}

– int arr[][COLS]: This syntax indicates that the function takes a 2D array of integers with a specified number of columns (COLS).
– size_t rows: This parameter can be used to pass the number of rows in the array.
– size_t cols: This parameter can be used to pass the number of columns in the array

  • Function Call:

When calling the function, you need to provide the actual 2D array along with the number of rows and columns.

int myArray[ROWS][COLS];
functionName(myArray, ROWS, COLS);

– myArray: The name of the 2D array you want to pass.
– ROWS: The number of rows in the array.
– COLS: The number of columns in the array.

Example 5:

#include <iostream>
using namespace std;
void f(int arr[][5], int r)
{
    for (size_t i = 0; i < r; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int main()
{
    int a[2][5] = {1,2,3,4,5,
                   10,20,30,40,50};
    f(a, 2);
    return 0;
}

The function f takes a 2D array (arr) and its number of rows (r) as parameters.
It uses nested loops to iterate over each element of the array and prints the elements in a tabular form.

The main function calls the function f with the 2D array a and the number of rows (2) as arguments.

Output:

The output of this code would be the elements of the 2D array a printed in a tabular form.

The printed output would look like:

1 2 3 4 5 
10 20 30 40 50 
  • Transpose matrix

The transpose of a matrix is an operation that flips the matrix over its diagonal, switching the row and column indices of the matrix. In other words, if the original matrix has elements at position (i, j), the transposed matrix will have the element at position (j, i).

Example 6:

#include <iostream>
using namespace std;
int main()
{
    int arr[3][3];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cin >> arr[i][j];
        }
    }
    cout << "Matrix is: \n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    cout << "Transpose matrix is:\n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[j][i] << " ";
        }
        cout << endl;
    }

    return 0;
}

This code takes user input for a 3×3 matrix, prints the original matrix, and then prints its transpose.

Here are the key points:

  1. Input:
    The nested loops take user input for a 3×3 matrix.
  2. Original Matrix Output:
    After taking input, the code outputs the original matrix.
  3. Transpose Matrix Output:
    Another set of nested loops outputs the transpose of the matrix. It switches the row and column indices.

Example Output:

If the user enters:

1 2 3
1 2 3
1 2 3

The output would be:

Matrix is: 
1 2 3 
1 2 3 
1 2 3 
Transpose matrix is:
1 1 1 
2 2 2 
3 3 3

 

Pointer

In C++, a pointer is a variable that stores the memory address of another variable. Pointers provide a powerful mechanism for working with memory and data structures. They allow direct manipulation of memory addresses and enable efficient memory management.

Declaring Pointers

To declare a pointer, you use the data type followed by an asterisk (*) and the pointer name. For example:

int *ptr; // Declares a pointer to an integer
double *dblPtr; // Declares a pointer to a double

Initializing Pointers

Pointers should be initialized before use. You can initialize a pointer by assigning the address of a variable to it. The address-of operator (&) is used to obtain the memory address of a variable.

int num = 10;
int *ptr = &num; // Initializes ptr with the address of num

Dereferencing Pointers

Dereferencing a pointer means accessing the value stored at the memory address it points to. The dereference operator (*) is used for this purpose.

int num = 10;
int *ptr = &num;

cout << *ptr; // Prints the value stored at the address pointed by ptr

Example 1:

#include <iostream>
using namespace std;

int main() {
    // Declaration of a pointer to an integer
    int *ptr;

    // Declaration and initialization of an integer variable
    int val = 5;

    // Assigning the address of 'val' to the pointer 'ptr'
    ptr = &val;

    // Printing the address stored in the pointer
    cout << ptr << endl;

    // Printing the value stored at the address pointed by 'ptr'
    cout << *ptr << endl;

    // Return 0 to indicate successful execution
    return 0;
}

This code declares a pointer, initializes an integer variable, assigns the address of that variable to the pointer, and then prints both the pointer’s value (memory address) and the value it points to.

Here are the key points:

  1. Pointer Declaration:
    int *ptr;: Declares a pointer to an integer. This pointer is currently uninitialized.
  2. Variable Declaration and Initialization:
    int val = 5;: Declares an integer variable named val and initializes it with the value 5.
  3. Assigning Address to Pointer:
    ptr = &val;: Assigns the memory address of the variable val to the pointer ptr. Now ptr “points” to the memory location of val.
  4. Printing Pointer’s Value (Memory Address):
    cout << ptr << endl;: Prints the memory address stored in the pointer ptr. The address is typically represented in hexadecimal format.
  5. Printing Value at the Address Pointed by Pointer:
    cout << *ptr << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by ptr. Prints the value stored in the variable val.

Output:
If you run this program, the output will be something like:

0x7ffee3c86a4c   // The memory address (this will vary on each run)
5                // The value stored at the memory address

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int *p;
    int v = 9;
    p = &v;
    cout << *p << endl;
    return 0;
}

This code prints the address of the value pointed to by the pointer p using the expressions &*p.

cout << &*p << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by p. The & operator then takes the address of this value. Essentially, &*p is equivalent to just p, so this line prints the memory address stored in the pointer p.

 

Pointer part 2 (Array vs Pointer & Passing Pointer To Function)

Arrays in C++

An array is a collection of elements of the same type stored in contiguous memory locations. In C++, arrays can be of primitive types (int, float, etc.) or user-defined types (structures, classes). Arrays have a fixed size, and the elements are accessed using an index.

int numbers[5] = {1, 2, 3, 4, 5};

Pointers in C++

A pointer is a variable that stores the memory address of another variable. Pointers allow for dynamic memory allocation and manipulation. They are often used for efficient memory management and for accessing elements in arrays.

int x = 10;
int *ptr = &x; // ptr now holds the address of x

Array vs. Pointer

In many contexts, arrays and pointers in C++ exhibit similar behavior. When an array name is used in an expression, it decays into a pointer to its first element. For example:

int arr[3] = {1, 2, 3};
int *ptr = arr; // Equivalent to &arr[0]

However, there are differences:

  • An array variable cannot be reassigned to point to a different memory location, whereas a pointer can.
  • Arrays carry information about their size, while pointers do not inherently know the size of the memory they point to.
  • Arrays can be used with the sizeof operator to determine their size, but pointers alone cannot.

Pointer Arithmetic

Pointers can be incremented or decremented to navigate through an array or block of memory.

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;

cout << *ptr; // Prints the first element (1)
ptr++;        // Moves to the next element
cout << *ptr; // Prints the second element (2)

 

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    for (size_t i = 0; i < 7; i++)
    {
        cout << *(arr + i) << endl;
    }
    return 0;
}

code prints the elements of an array using pointer arithmetic.

cout << *(arr + i) << endl;: Utilizes pointer arithmetic to access each element of the array. The expression arr + i calculates the memory address of the i-th element, and *(arr + i) dereferences the pointer to access the value stored at that address.

Output:
If you run this program, the output will be:

11
22
33
44
55
66
77

 

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    int *ptr;
    ptr = arr;
    for (size_t i = 0; i < 7; i++)
    {
        cout << *ptr << " ";
        ptr++;
    }
    return 0;
}

This code accomplishes the same goal as the previous example but uses a pointer (ptr) and pointer arithmetic to iterate through the array.

Output:
If you run this program, the output will be:

11 22 33 44 55 66 77

Passing Pointers to Functions

When passing an array to a function, you are actually passing a pointer to the first element of the array. This is due to the array decaying into a pointer in function arguments.

Example 3:

This code demonstrates the usage of pointers and a function that modifies the value it points to.

#include <iostream>
using namespace std;
int fun(int *p)
{
    *p = *p + 1;
    return *p;
}
int main()
{
    int x = 1;
    int *ptr = &x;
    cout << fun(ptr) << endl;
    cout << x << endl;
    cout << fun(&x) << endl;
    cout << x << endl;
    return 0;
}

Key points:

  1. Function fun:
    int fun(int *p): Takes a pointer to an integer as a parameter.
    *p = *p + 1;: Increments the value pointed to by the pointer.
    return *p;: Returns the updated value.
  2. Main Function:
    int x = 1;: Declares and initializes an integer variable x.
    int *ptr = &x;: Declares a pointer ptr and assigns the address of x to it.
    cout << fun(ptr) << endl;: Calls the function fun with the pointer ptr and prints the result. The value of x is now 2.
    cout << x << endl;: Prints the current value of x after the function call. It is now 2.
    cout << fun(&x) << endl;: Calls the function fun with the address of x directly and prints the result.
    The value of x is now 3.cout << x << endl;: Prints the final value of x. It is now 3.

Output:
If you run this program, the output will be:

2
2
3
3

 

Data Structures (struct)

In the world of programming, data structures play a pivotal role in how we organize and manipulate data efficiently. They act as the building blocks that enable us to create well-structured and organized programs. In this explanation, we will delve into one fundamental data structure in C++ known as struct.

What is a Data Structure?

Before we explore struct, let’s define what a data structure is. A data structure is a way of organizing and storing data in a computer’s memory to perform operations on that data more efficiently. It provides a blueprint for the storage and retrieval of information.

Introduction to struct in C++

struct in C++ is a user-defined data type that allows you to group together variables of different data types under a single name. Think of it as creating a custom data type tailored to the specific needs of your program. This makes your code more modular, organized, and easier to understand.

Syntax of struct:

The syntax for defining a struct is straightforward:

struct MyStruct

struct MyStruct

Example 1:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x;
    x.name = "Rolls-Royce";
    x.color = "Red";
    x.model = 2019;
    x.maxSpeed = 270;
    
    cout << x.name << endl;
    return 0;
}

code defines a struct named car that represents information about a car, and it creates an instance of this struct called x to store details about a specific car.

Key points:

  • Struct Definition (car):
    The struct named car has four member variables: name, color, maxSpeed, and model. These variables store information about a car.
  • Instance Creation (x):
    An instance of the car struct named x is created in the main function. This instance can store information about a specific car.
  • Assigning Values:
    Values are assigned to the member variables of the x instance using the dot (.) notation. For example, x.name = “Rolls-Royce” assigns the name “Rolls-Royce” to the name member variable.
  • Printing Information:
    The program prints the name of the car using cout << x.name << endl;. In this case, it will output “Rolls-Royce” to the console.

Output:
If you run this program, the output will be:

Rolls-Royce

Example 2:

Here is another way of initialization the values based on the previous example:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    cout << x.maxSpeed << endl;
    return 0;
}

Output:

250

Example 3:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = x;
    cout << y.name << endl;
    return 0;
}

Instance Creation and Initialization (x and y):

  • An instance of the car struct named x is created with initial values.
  • Another instance named y is created and initialized with the values of x. This is a memberwise copy, and each member of y gets the value of the corresponding member in x.

Example 4:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
}y;
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = {"Mercedes","Red",300,2016};
    if (x.maxSpeed > y.maxSpeed)
        cout << "car x is faster than car y";
    else
        cout << "car y is faster than car x";
    return 0;
}
  • Global Instance Declaration (y):
    An instance of the car struct named y is declared at the global scope. This means it can be accessed throughout the program.
  • Instance Creation and Initialization (x and Local y):
    – A local instance of the car struct named x is created with initial values.
    – Another local instance named y is created with different values. This y is local to the main function and shadows the global y within this scope.
  • Comparison and Output:
    The program compares the maximum speeds of cars x and y and prints a message indicating which car is faster.

Output:
If you run this program, the output will depend on the values assigned to maxSpeed in x and y. For the provided values, it will output:

car y is faster than car x

Pass ‘struct’ into function:

Example 5:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
void f(car f)
{
    cout << "Name = " << f.name << endl;
    cout << "Color = " << f.color << endl;
}
int main()
{
    car v = {"No name","Red",160,2000};
    f(v);
    return 0;
}

Key points:

  • Function Definition (f):
    The function f takes a car as a parameter and prints information about the car, specifically the name and color.
  • Instance Creation and Initialization (v):
    An instance of the car struct named v is created with initial values.
  • Function Call (f(v)):
    The program calls the function f with the v instance as an argument.

Output:
If you run this program, the output will be:

Name = No name
Color = Red

Example 6:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
car read_return(car&s)
{
    cout << "Enter car name:\n";
    cin >> s.name;
    cout << "Enter car color:\n";
    cin >> s.color;
    cout << "Enter car maximum speed:\n";
    cin >> s.maxSpeed;
    cout << "Enter car model:\n";
    cin >> s.model;
    return s;
}
int main()
{
    car v;
    read_return(v);
    car h;
    h = v;
    cout << h.name << endl;
    return 0;
}

Key points:

  • Function Definition (read_return):
    The function read_return takes a car reference as a parameter, reads input to populate its fields, and returns the modified car struct.
  • Function Call (read_return(v)):
    The program calls the function read_return with the v instance as a reference, allowing the function to modify the values of v.
  • Assignment and Printing:
    – The values of v are assigned to h.
    – The program prints the name of h.

Output:
If you run this program and enter values when prompted, the output will depend on the input provided. For example:

Enter car name:
BMW
Enter car color:
Blue
Enter car maximum speed:
250
Enter car model:
2022
BMW

Example 7:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car v = {"Kia"};
    v.fun(v);
    return 0;
}

Key points:

  • Member Function Definition (fun):
    The member function fun is defined inside the car struct.
    It takes a car as a parameter and prints its name.

Output:
If you run this program, the output will be:

Kia

Example 8:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car*h;
    car b = {"Toyota","Red",170,2008};
    h = &b;
    cout << h->color << endl;
    return 0;
}

Key points:

  • Pointer Declaration and Initialization (h):
    A pointer to a car named h is declared.
  • Instance Creation and Initialization (b):
    An instance of the car struct named b is created and initialized with specific values.
  • Pointer Assignment (h = &b):
    The address of b is assigned to the pointer h.
  • Pointer Dereferencing (h->color):
    The program prints the color of the car pointed to by h using the arrow operator (->).

Output:
If you run this program, the output will be:

Red

 

String

In C++, a string is a sequence of characters represented using the string class. Unlike C-style strings, which are arrays of characters, C++ strings are dynamic and provide a higher level of abstraction. The string class is part of the C++ Standard Template Library (STL), making it convenient and powerful for handling strings.

Declaring and Initializing Strings:

You can declare a string using the string keyword and initialize it in various ways:

// Declare and initialize strings
string str1 = "Hello, ";  // Initialization using a string literal
string str2("world!");    // Initialization using a constructor

// Concatenate strings
string result = str1 + str2;

When you use a string in C++, you must include its library this way:

#include <string>

Example:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string x = "Ahmad", y;
    y.assign(x);
    cout << "y = " << y << endl;

    return 0;
}

String Assignment:

  • string y;: Declares another string variable y.
  • y.assign(x);: Uses the assign method to copy the contents of string x to string y.

Output:

y = Ahmad

String Methods in C++:

Below is an explanation of various string methods in C++, along with their parameters and examples:

  1. at Method:
    Description: Returns the character at a specified position in the string.
    Parameters: Takes an index as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.at(0) << endl;
    
    // A
  2. length Method:
    Description: Returns the number of characters in the string.
    Parameters: No parameters.
    Example:

     string x = "Ahmad";
     cout << x.length() << endl;
    
     // 5
  3. size Method:
    Description: Same as length, returns the number of characters in the string.
    Parameters: No parameters.
    Example:

    string x = "Ahmad";
    cout << x.size() << endl;
    
    // 5
  4. substr Method:
    Description: Returns a substring of the original string.
    Parameters: Takes starting index and length as parameters.
    Example:

    string x = "Ahmad";
    cout << x.substr(1,3) << endl;
    
    // hma
  5. swap Method:
    Description: Swaps the content of two strings.
    Parameters: Takes another string as a parameter.
    Example:

    string x = "Ahmad", y = "Ali";
    cout << x.swap(y) << endl;
    
    // Swaps the content of x and y
  6. find Method:
    Description: Finds the first occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.find('a') << endl;
    
    // 3
  7. rfind Method:
    Description: Finds the last occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.rfind('a') << endl;
    
    // 3
  8. erase Method:
    Description: Erases characters from the string.
    Parameters: Takes starting index and count as parameters.
    Example:

    string x = "Ahmad";
    cout << x.erase(0,3) << endl;
    
    // ad
  9. replace Method:
    Description: Replaces a portion of the string with another string.
    Parameters: Takes starting index, length, and replacement string as parameters.
    Example:

    string x = "Ahmad";
    cout << x.replace(1,4,"li") << endl;
    
    // Ali
  10. insert Method:
    Description: Inserts characters into the string.
    Parameters: Takes starting index and string to insert as parameters.
    Example:

    string x = "Ahmad";
    cout << x.insert(5," Ali") << endl;
    
    // Ahmad Ali

These are some commonly used string methods in C++. Remember to include the <string> header for using these methods.

OOP in C++

Object-Oriented Programming (OOP) is an acronym that stands for the following concepts:

In procedural programming, the emphasis lies in writing procedures or functions designed to perform operations on data. In contrast, object-oriented programming revolves around the creation of objects that encapsulate both data and functions.

Object-oriented programming offers numerous advantages over procedural programming:

  1. OOP execution is typically faster and more straightforward.
  2. OOP provides a well-defined structure for organizing programs.
  3. OOP promotes the “Don’t Repeat Yourself” (DRY) principle in C++, reducing code duplication and enhancing code maintainability, modification, and debugging.
  4. OOP facilitates the development of highly reusable applications with reduced code volume and shorter development timelines.

As a helpful tip, adhering to the “Don’t Repeat Yourself” (DRY) principle involves identifying and extracting common code segments within an application, centralizing them for reuse rather than duplicating them throughout the codebase.

Review Function

The Structure of C++ program

#include <iostream>
using namespace std;

int main()
{
    cout << "Welcome to OOP in C++" << endl;

    return 0;
}

Let’s break down the structure and purpose of each command line in the provided C++ code:

#include <iostream>

Structure: This line begins with the #include preprocessor directive, followed by the <iostream> header file enclosed in angle brackets.

Purpose: This line includes the Input/Output Stream Library (iostream), which is essential for performing input and output operations in C++. It provides functionalities like cin for input and cout for output.

using namespace std;

Structure: The using namespace std; line declares that the code will be using the std namespace.

Purpose: The std namespace contains the standard C++ library components, including the cout and endl used in the code. By including this line, you can use these components without explicitly specifying the namespace each time you use them.

int main()
{

Structure: This line marks the beginning of the main function, which is the entry point of every C++ program.

Purpose: The main function is where the program execution starts. It is required in every C++ program, and the code within the curly braces {} defines the body of the main function.

cout << "Welcome to OOP in C++" << endl;

Structure: This line uses the cout object to output the text “Welcome to OOP in C++” to the console. The << operator is used for streaming the text to the output.

Purpose: This line is responsible for displaying a welcome message on the console, indicating that the program is focused on Object-Oriented Programming (OOP) in C++.

    return 0;
}

Structure: The return 0; line signifies the end of the main function. The 0 is returned to the operating system, indicating that the program executed successfully.

Purpose: The return 0; line is a common way to indicate a successful termination of the program. The value 0 is typically returned to the operating system to signify that the program executed without errors.

Libraries in C++

In C++, a library is a collection of pre-compiled functions, classes, and procedures that can be used by a program. These libraries provide a set of functionalities that can be utilized to perform common tasks, ranging from basic input/output operations to complex mathematical computations. Libraries offer a way to modularize code, promote code reuse, and streamline development by providing ready-made solutions for various tasks.

Here are some key aspects of libraries in C++:

  1. Standard Template Library (STL):
    The C++ Standard Library, often referred to as the Standard Template Library (STL), is a core part of C++. It includes a wide range of generic algorithms (e.g., sorting, searching) and data structures (e.g., vectors, lists, maps) that are implemented using templates. The STL simplifies programming by providing efficient and generic solutions to common problems.
  2. Header Files:
    C++ libraries are typically distributed as header files (with the extension .h or .hpp) and implementation files (with the extension .cpp). Header files contain declarations of functions, classes, and other entities that can be used in your program, while the implementation files contain the actual code.
  3. IOStream Library:
    The iostream library is a fundamental part of the C++ Standard Library and provides functionality for input and output operations. It includes cin (for input) and cout (for output), among other stream classes. Here’s an example of using the iostream library:

    #include <iostream>
    
    int main() {
        std::cout << "Hello, C++!" << std::endl;
        return 0;
    }
    
  4. Math Library:
    The cmath library provides a set of mathematical functions, such as trigonometric, logarithmic, and exponential functions.
  5. User-Defined Libraries:
    Apart from the standard libraries, you can create your own libraries to encapsulate and organize your code. This involves creating header files that declare the functions and classes, and implementation files that define their behavior. You can then include your custom library in other C++ programs.

Function in C++

In the realm of programming, functions play a pivotal role in organizing code, enhancing reusability, and promoting a structured approach to problem-solving. In C++, a function is a self-contained unit of code designed to perform a specific task or achieve a particular objective. It encapsulates a set of instructions, allowing you to break down a complex program into smaller, more manageable pieces.

Key Concepts
1. Modularity:
Functions enable the decomposition of a program into smaller, more manageable modules. Each function handles a specific aspect of the overall functionality, promoting a modular and organized code structure.

2. Reusability:
Once a function is defined, it can be reused in different parts of the program or even in other programs. This promotes the “Don’t Repeat Yourself” (DRY) principle, saving both time and effort.

3. Abstraction:
Functions provide a level of abstraction, allowing you to focus on high-level functionality without getting bogged down by the implementation details. This abstraction enhances code readability and simplifies the debugging process.

4. Parameters and Return Values:
Functions can accept input parameters and return values, allowing for dynamic and interactive code. Parameters provide a way to pass information into a function, while return values allow functions to communicate results back to the calling code.

Basic Syntax
A typical C++ function follows this basic syntax:

returnType functionName(parameterType1 parameterName1, parameterType2 parameterName2, ...) {
    // Function body: Code to perform the desired task
    // Optionally, a return statement to provide a result back to the caller
}

Let’s break down the components:

returnType: Specifies the type of data the function will return (if any).
functionName: The unique identifier for the function.
parameters: Input values that the function receives.
functionBody: The set of instructions defining the function’s behavior.

Example 1:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    return x + y;
}

int main()
{
    cout << sum(10,20) << endl;
    return 0;
}

This C++ code is a simple program that calculates and displays the sum of two numbers.

  • Define a Sum Function:
int sum(int x, int y)
{
    return x + y;
}

This block of code creates a function called sum. It takes in two numbers (x and y) and gives back their sum.

  • Use the Sum Function in the Main Part:
int main()
{
    cout << sum(10, 20) << endl;
    return 0;
}

Here, the main part is like the director of the program. It says, “Hey, calculate the sum of 10 and 20 using the sum function, and show me the result on the screen.” The endl is like pressing Enter on the keyboard; it moves to the next line.

  • Run the Program:

When you run this program, it does the calculation (10 + 20) inside the sum function, then displays the result (30) on the screen. The return 0; part tells the computer that everything went well.

 

Of course, the user can enter the data to be calculated using cin, using this command:

cin >> x >> y;

This command can be located inside the main function, but it’s better to use it inside the function itself to have a cleaner code.
See the following example:

#include <iostream>

using namespace std;
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;

    return 0;
}

This code asks the user to input two numbers, adds them together, and then displays the result.

  • Define a Sum Function:
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}

This block of code defines a function called sum. It asks the user to enter two numbers, reads those numbers from the keyboard (cin), and then returns the sum of those numbers.

  • Use the Sum Function in the Main Part:
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;
    return 0;
}

In the main part, it starts with x and y set to 0. It then calls the sum function, passing x and y as arguments. The sum function gets user input, adds the numbers, and returns the result. The result is stored in z. Finally, it displays the sum with a message using cout.

So, in a nutshell, this program is like a simple interactive calculator. It asks you for two numbers, adds them together, and then shows you the result on the screen.

Providing initial values to variables is crucial to avoid errors.

Example 2:

#include <iostream>
using namespace std;

double avg(double m1, double m2, double m3)
{
    return (m1 + m2 + m3) / 3;
}

int main()
{
    cout << avg(100, 60, 50);
    return 0;
}

This code calculates and displays the average of three numbers.

The avg function takes in three numbers (m1, m2, and m3), adds them together, divides by 3, and returns the result. This is how you calculate the average of three numbers.
In the main part, it directly calls the avg function with three numbers (100, 60, and 50) as arguments. It then uses cout to display the result, which is the average of these three numbers.

Example 3:

#include <iostream>
using namespace std;

int max(int n1, int n2, int n3)
{
    int m = n1;
    if (m < n2)
        m = n2;
    if (m < n3)
        m = n3;
    return m;
}

int main()
{
    cout << max(100, 20, 800);
    return 0;
}

This code finds and displays the maximum of three numbers.

The max function takes in three numbers (n1, n2, and n3) and uses conditional statements (if) to determine the maximum among them. It begins by considering n1 as the initial maximum value and then employs conditional statements (if) to compare it with the other values. Whenever the condition is met, the maximum value is updated. The maximum value is then returned.

In the main part, it directly calls the max function with three numbers (100, 20, and 800) as arguments. It then uses cout to display the result, which is the maximum of these three numbers.

We can find a minimum value among other values using the same logic but changing the conditions.

Example 4:

#include <iostream>
using namespace std;

void p()
{
    cout << "myName\n";
}

int main()
{
    p();
    return 0;
}

This code defines a function and then calls that function in the main part of the program.

The function called p used void keyword before the function name which means that this function doesn’t return any value. Inside the function, it uses cout to display the text “myName” on the screen.

In the main part, it calls the p function. When a function is called, the program jumps to that function, performs the tasks inside it, and then returns to where it was called. In this case, it jumps to the p function, prints “myName” to the screen, and then returns to the main function.

  • Now, let’s talk about the concept of a void function:

A void function is a function that doesn’t return a value. In this example, the p function is a void function because it has the void keyword before its name.

Void functions are useful when you want a function to perform a task or set of tasks without needing to provide a result back to the part of the program that called it.

Example 5:

#include <iostream>
using namespace std;

int mul(int x = 10, int y = 50)
{
    return x*y;
}

int main()
{
    cout << mul(10) << endl;
    cout << mul(10, 2) << endl;
    cout << mul() << endl;

    return 0;
}

This code demonstrates the use of default arguments in a function.

The function called mul multiplies two numbers (x and y). The interesting part is that both x and y have default values assigned (10 and 50, respectively). If these values are not provided when the function is called, these defaults will be used.

In the main part, it calls the mul function multiple times with different combinations of arguments:

mul(10): It uses the default value 50 for y, so it multiplies 10 by 50.
mul(10, 2): It uses both 10 and 2 provided as arguments, so it multiplies 10 by 2.
mul(): Since no arguments are provided, it uses both default values (10 and 50), so it multiplies 10 by 50.

  • Now, let’s talk about the concept of default arguments:

Default arguments allow you to provide values to parameters in a function declaration, so if the caller doesn’t provide values, the default values are used.

In this example, the mul function has default values for both x and y, making it flexible when calling the function with different numbers of arguments.

Example 6:

#include <iostream>
using namespace std;

void ref(int &x, int &y)
{
    x += 1;
    y += 1;
}

int main()
{
    int p = 0, t = 0;
    ref(p, t);
    cout << "p = " << p << endl;
    cout << "t = " << t << endl;
    return 0;
}

This code demonstrates the concept of “call by reference.”

The function called ref has an interesting part which is that it takes references (&x and &y) as parameters, indicating that it will directly modify the values of the variables passed to it.

In the main part, it declares two variables (p and t) and initializes them to 0. Then, it calls the ref function with p and t as arguments. Inside the ref function, both p and t are increased by 1. Finally, it prints the values of p and t after the function call using cout.

  • Now, let’s talk about the concept of call by reference:

In C++, when you pass parameters to a function by reference (using &), the function receives the memory addresses of the actual variables, not just copies of their values.

This means any changes made to the parameters inside the function directly affect the original variables outside the function.

In this example, the ref function modifies the values of p and t directly because they are passed by reference.

Built-in functions

Built-in functions in C++ are pre-defined functions provided by the C++ programming language. These functions are part of the standard C++ library and offer ready-made solutions for common tasks. They are designed to perform specific operations and can be used by programmers without the need to write the entire code for those operations.

Here’s a simple breakdown:

  • Ready-made Tools:
    Built-in functions are like tools that are already available for you to use. Instead of creating these tools from scratch, you can simply use the built-in functions to perform various tasks.
  • Part of the Standard C++ Library:
    These functions are part of the standard C++ library, which is a collection of tools and functionalities that come with every C++ compiler. You don’t need to create or install anything extra to use them.
  • Common Operations:
    Built-in functions are designed to perform common operations such as input/output, mathematical calculations, string manipulations, and more. Examples include cout and cin for printing and reading from the console, sqrt for square root, and strlen for getting the length of a string.
  • Saves Coding Time:
    By using built-in functions, you can save a lot of time and effort. You don’t need to write complex code for tasks that are already handled by these functions.
  • Consistency Across Platforms:
    Since these functions are part of the standard library, they provide a consistent way to perform operations across different platforms and compilers. This makes your code more portable and ensures it works similarly on various systems.

In essence, built-in functions in C++ are like a toolbox that comes with the language. They provide a set of tools you can use to make your programming tasks easier, faster, and more standardized. As you become more familiar with C++, you’ll discover and leverage these functions to streamline your code.

Here are some common built-in functions in C++:

  1. Input/Output Functions:
    cout: Used to display output to the console.
    cin: Used to take input from the user through the console.
  2. Mathematical Functions:
    sqrt(): Calculates the square root of a number.
    abs(): Returns the absolute value of a number.
    pow(): Raises a number to a specified power.
  3. String Functions:
    strlen(): Returns the length of a string.
    strcpy(): Copies one string to another.
    strcat(): Concatenates (joins) two strings.
  4. Character Functions:
    isalpha(): Checks if a character is an alphabet letter.
    isdigit(): Checks if a character is a digit.
    toupper(): Converts a character to uppercase.
  5. Array Functions:
    sizeof(): Returns the size of a data type or an array.
    sort(): Sorts elements in an array in ascending order.
  6. Memory Functions:
    malloc(): Allocates a specified amount of memory dynamically.
    free(): Releases memory that was previously allocated with malloc.
  7. Time and Date Functions:
    time(): Returns the current time in seconds.
    ctime(): Converts a time value into a string representation.

Example 7:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    cout << abs(-10) << endl;
    cout << max(10, 20) << endl;
    cout << max(max(10, 20), 30) << endl;
    int x = 10, y = 20;
    swap(x,y);
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    
    return 0;
}

This code demonstrates the usage of several built-in functions from the <cmath> and <algorithm> libraries.

  • abs(-10): Calculates the absolute value of -10 and prints the result (10) to the console.
  • max(10, 20): Finds the maximum of two numbers (10 and 20) and prints the result (20) to the console.
  • max(max(10, 20), 30): Compares three numbers (10, 20, and 30) and finds the maximum among them. It prints the result (30) to the console.
  • swap(x, y): Swaps the values of x and y. After this line, x will be 20, and y will be 10.

Output:

10
20
30
x = 20
y = 10

 

 

Review Arrays

What is an Array?

An array is a fundamental data structure in C++ that allows you to store multiple elements of the same data type under a single name. These elements can be accessed using an index, making arrays a powerful tool for handling collections of data efficiently.

Declaration and Initialization:

In C++, declaring an array involves specifying the data type of its elements and the array’s name. Initialization can be done during declaration or later using assignment statements. Let’s take a look at the syntax:

// Declaration
int myArray[5];

// Initialization during declaration
int anotherArray[] = {1, 2, 3, 4, 5};

// Accessing elements
cout << anotherArray[2]; // Output: 3

Array Indexing:
Array indexing starts from 0, meaning the first element is accessed using index 0, the second with index 1, and so on. Be cautious not to access elements beyond the array’s bounds, as it can lead to undefined behavior.

Manipulating Arrays:
Iterating Through an Array:
Looping through an array is a common operation. You can use a for loop to access each element:

for (int i = 0; i < 5; ++i) {
    cout << myArray[i] << " ";
}

Array Size:
Determining the size of an array is crucial for avoiding index out-of-bounds errors. You can use the sizeof operator or calculate the size using the number of elements and data type size:

int size = sizeof(anotherArray) / sizeof(anotherArray[0]);

Example 1:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }
    
    for (int i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }

    return 0;
}

This program takes input for an array of integers and then prints the entered values.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }

    for (int i = 0; i < 7; i++)
    {
        cout << "index" << i << " = " << arr[i];
        cout << endl;
    }
    cout << endl;

    return 0;
}

This program is a simple console application that takes input for an array of 7 integers from the user and then displays each element along with its index.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    char g[5];
    cin.get(g, 5);
    cout << g << endl;

    return 0;
}

This program demonstrates reading a character array from user input using cin.get().

char g[5];
This line declares a character array named g that can hold 5 characters.

cin.get(g, 5);
This line uses cin.get() to read up to 4 characters (since the array size is 5, one space is reserved for the null terminator \0) from the user and stores them in the character array g. It stops reading when it encounters a newline character, the end of the stream, or when the specified number of characters have been read.

In summary, this program prompts the user to enter up to 4 characters (excluding the null terminator) and then prints the entered characters using cout.

The null terminator

Often represented by the character \0 (backslash followed by zero), is a special character used in C and C++ to denote the end of a string. It is essential for string manipulation functions to determine where a string ends in memory.

In memory, a string is represented as an array of characters. The null terminator is placed at the end of this array to indicate the boundary of the string. When a program processes a string, it can keep reading characters until it encounters the null terminator, signifying the end of the string data.

For example:

const char myString[] = "Hello";

In memory, this would be stored as follows:

H   e   l   l   o   \0

Here, the null terminator \0 follows the characters of the string, indicating the end of the string. Functions that operate on strings, like those in the C Standard Library or C++ Standard Library, use the null terminator to determine the length of the string and to recognize the end of the string when performing operations.

Example 4:

#include <iostream>
using namespace std;

int main()
{
    char g1[10];
    char g2[10];
    cin.getline(g1, 10);
    cin.getline(g2, 10);
    
    cout << g1 << endl;
    cout << g2 << endl;

    return 0;
}

This program demonstrates the use of the cin.getline() function to read input lines into character arrays and then prints them.

char g1[10];
char g2[10];

These lines declare two character arrays, g1 and g2, each capable of holding up to 9 characters plus the null terminator \0.

cin.getline(g1, 10);
cin.getline(g2, 10);

These lines use cin.getline() to read lines of input from the user into the character arrays g1 and g2. The function takes two arguments: the array to store the input (g1 or g2) and the maximum number of characters to read (9 in this case, leaving one space for the null terminator). The getline function reads characters until it encounters a newline character (‘\n’) or reaches the specified limit.

In summary, this program allows the user to input two lines of text, each up to 9 characters long, and then prints the entered lines. The use of cin.getline() ensures that the input is read as a line, and the program avoids potential issues with the input buffer.

Example 5:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char a1[] = "A";
    char a2[] = "B";
    cout << strcmp(a1, a2);

    return 0;
}

This C++ program compares two strings using the strcmp function from the C Standard Library.

This code includes the necessary header files for input/output operations (iostream) and string-related functions (cstring). The cstring header is included for the strcmp function.

char a1[] = "A";
char a2[] = "B";

These lines declare and initialize two character arrays, a1 and a2. Each array contains a single character and is automatically null-terminated by the compiler. Remember that a string in C/C++ is essentially an array of characters terminated by the null character (‘\0’).

cout << strcmp(a1, a2);

This line uses the strcmp function to compare the strings stored in a1 and a2. The result is printed to the console. The strcmp function returns an integer value:

  • If the strings are equal, it returns 0.
  • If a1 is lexicographically less than a2, it returns a negative value.
  • If a1 is lexicographically greater than a2, it returns a positive value.

The result of the comparison is printed to the console. This will be either 0 if the strings are equal, a negative value if a1 is less than a2, or a positive value if a1 is greater than a2.

 

Multi-dimensional Arrays:
C++ supports multi-dimensional arrays, which can be thought of as arrays of arrays. A 2D array, for example, can be declared and accessed like this:

int matrix[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

Additional Tips:
Passing Arrays to Functions:
When passing an array to a function, you need to use pointers. Here’s a quick example:

void printArray(int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
}

Standard Template Library (STL) Arrays:
For more advanced functionalities, consider using the array class from the C++ Standard Template Library (STL). It provides additional features and safety checks.

#include <array>

std::array<int, 5> stlArray = {1, 2, 3, 4, 5};

Example 6:

#include <iostream>
#include <cstring>
using namespace std;

void search(int arr[], int s, int k)
{
    bool g = false;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] == k)
            g = true;
    }
    if (g)
        cout << "Found\n";
    else
        cout << "Not Found\n";
}

int main()
{
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    search(arr, 7, 55);
    

    return 0;
}

This program defines a function called search that searches for a specific value in an integer array. The main function then calls this search function to check if a particular value is present in the given array.

The function called search takes three parameters: arr (an integer array), s (the size of the array), and k (the value to search for).
It initializes a boolean variable g to false, which will be used to track whether the value k is found in the array.
The function then iterates through the array using a for loop. If the current element is equal to the target value k, it sets g to true.
After the loop, it checks the value of g and prints either “Found” or “Not Found” based on whether the target value was found in the array.

The main function initializes an integer array arr with values.
It then calls the search function, passing the array arr, the size of the array (7), and the value to search for (55).

Depending on whether the value 55 is found in the array, the program will output either “Found” or “Not Found.”

Example 7:

#include <iostream>
using namespace std;

void sort(int arr[], int s)
{
    int t;
    for (size_t i = 0; i < s - 1; i++)
    {
        for (size_t j = 0; j < s - 1; j++)
        {
            if (arr[j] > arr[j+1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
}

int main()
{
    int t;
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    sort(arr, 7);
    for (size_t i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }
    return 0;
}

This program implements a simple sorting algorithm known as the Bubble Sort.

The sort function implements the Bubble Sort algorithm for sorting an array of integers.
It takes two parameters: arr (the integer array to be sorted) and s (the size of the array).
The function uses nested for loops to iterate through the array. The inner loop compares adjacent elements and swaps them if they are in the wrong order, pushing the larger element towards the end of the array.
The process repeats until the entire array is sorted in ascending order.

The main function initializes an integer array arr with values.
It then calls the sort function, passing the array arr and its size (7), which sorts the array using the Bubble Sort algorithm.
Finally, the sorted array is printed using a for loop.

The program will output the sorted array: 0 1 7 22 55 88 99

Conclusion:
Mastering arrays in C++ is a crucial step in becoming a proficient programmer. They serve as the building blocks for more complex data structures and algorithms. If you’ve found this review helpful, don’t forget to check out our video tutorials on [Adel Nasim] for hands-on examples and practical insights.

Classes

What is a Class?

In C++, a class is a user-defined data type that encapsulates data and the functions that operate on that data. It serves as a blueprint for creating objects, which are instances of the class. Imagine a class as a template that defines the structure and behavior of objects.

To declare a class in C++, you use the class keyword.

Once a class is defined, you can create objects of that class. Objects are instances of the class, each with its own set of data.

In C++, classes support access modifiers like public, private, and protected. These modifiers control the visibility and accessibility of class members.

Example 1:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

class car{
    private: 
        char name[15];
        char color[10];
        int maxSpeed;
        int model;
    public:
        void setName(char n[])
        {
            strcpy_s(name, n);
        }
        void setColor(char n[])
        {
            strcpy_s(color, n);
        }
        void setMaxSpeed(int m)
        {
            maxSpeed = m;
        }
        void setModel(int m)
        {
            model = m;
        }
        char* getName()
        {
            return name;
        }
        char* getColor()
        {
            return color;
        }
        int getMaxSpeed()
        {
            return maxSpeed;
        }
        int getModel()
        {
            return model;
        }
        void print()
        {
            cout << "name = " << name << "\n"
            << "color = " << color << "\n"
            << "maxspeed = " << maxSpeed << "\n"
            << "model = " << model << "\n";
        }
};
int main()
{
    car x;
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);
    x.print();
    return 0;
}

This C++ code defines a simple class named car that represents information about a car, such as its name, color, maximum speed, and model. The program creates an instance of this class, sets its attributes, and prints the details using member functions. Let’s break down the code step by step:

  • Class Definition: car
class car {
private: 
    char name[15];
    char color[10];
    int maxSpeed;
    int model;
public:
    // Member functions for setting attributes
    void setName(char n[]) { strcpy_s(name, n); }
    void setColor(char n[]) { strcpy_s(color, n); }
    void setMaxSpeed(int m) { maxSpeed = m; }
    void setModel(int m) { model = m; }

    // Member functions for retrieving attributes
    char* getName() { return name; }
    char* getColor() { return color; }
    int getMaxSpeed() { return maxSpeed; }
    int getModel() { return model; }

    // Member function to print details
    void print() {
        cout << "name = " << name << "\n"
             << "color = " << color << "\n"
             << "maxspeed = " << maxSpeed << "\n"
             << "model = " << model << "\n";
    }
};

– Private Members: The class has private member variables (name, color, maxSpeed, and model), which can only be accessed within the class.

– Public Members: The class provides public member functions (setName, setColor, setMaxSpeed, etc.) to set and retrieve the values of these private variables.

  • main Function:
int main() {
    car x;

    // Setting attributes of the car
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);

    // Printing the details using the print() member function
    x.print();

    return 0;
}

– Object Creation: An object x of type car is created.

– Setting Attributes: The attributes of the car (name, color, maxSpeed, and model) are set using the member functions (setName, setColor, setMaxSpeed, and setModel).

– Printing Details: The details of the car are printed using the print member function, which displays the values of the car’s attributes.

The output of this program would be:

name = kia
color = red
maxspeed = 300
model = 2017

This demonstrates a simple usage of a class in C++, encapsulating data and behavior related to a car. The class provides methods to set and retrieve attributes, promoting encapsulation and data hiding. This is a fundamental concept in object-oriented programming.

Example 2:

#include <iostream>
using namespace std;

class triangle{
    private: 
        float base;
        float height;
    public:
        void setBase_height(float b, float h)
        {
            base = b;
            height = h;
        }
        float area()
        {
            return 0.5 * base * height;
        }
        void print()
        {
            cout << "base = " << base << endl
            << "height = " << height << endl
            << "area = " << area() << endl;
        }
};
int main()
{
    triangle ob;
    ob.setBase_height(5, 10);
    ob.print();
    return 0;
}

This code defines a class named triangle that represents a triangle. The class has private member variables for the base and height of the triangle, and it provides member functions for setting these values, calculating the area, and printing the details of the triangle. Let’s break down the code step by step:

  • Class Definition: triangle
class triangle {
private: 
    float base;
    float height;

public:
    // Member function to set base and height
    void setBase_height(float b, float h) {
        base = b;
        height = h;
    }

    // Member function to calculate the area of the triangle
    float area() {
        return 0.5 * base * height;
    }

    // Member function to print details of the triangle
    void print() {
        cout << "base = " << base << endl
             << "height = " << height << endl
             << "area = " << area() << endl;
    }
};

– Private Members: The class has private member variables base and height, which can only be accessed within the class.

– Public Members: The class provides public member functions (setBase_height, area, and print) to set the base and height, calculate the area, and print the details of the triangle.

  • main Function:
int main() {
    triangle ob;

    // Setting base and height of the triangle
    ob.setBase_height(5, 10);

    // Printing the details of the triangle
    ob.print();

    return 0;
}

– Object Creation: An object ob of type triangle is created.

– Setting Base and Height: The setBase_height member function is called to set the base to 5 and height to 10 for the triangle.

– Printing Details: The print member function is called to print the details of the triangle, including the base, height, and calculated area.

The output of this program would be:

base = 5
height = 10
area = 25

This demonstrates a basic usage of a class in C++ to represent and manipulate data related to a triangle. The class encapsulates the data and behavior related to the triangle, promoting encapsulation and making the code more organized and reusable. The program calculates and displays the area of the triangle using the provided member functions.

Constructors

What is a Constructor?
In C++, a constructor is a special member function within a class that is automatically invoked when an object of that class is created. Its primary purpose is to initialize the object’s data members or perform any necessary setup for the object. Constructors ensure that the object starts with a valid state.

  1. Constructor Name:
    Constructors have the same name as the class they belong to.
  2. No Return Value:
    Constructors do not return any value, not even void.
  3. Object Initialization:
    Constructors are used to initialize and set up a new object when it is created.

Types of Constructors:

  1. Default/ Empty Constructor:
    Automatically generated by the compiler if no constructor is explicitly defined.
    Initializes object members with default values.
    Syntax: ClassName() { /* Initialization code */ }
    Example 1:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height =h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob;
        ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }

    An empty constructor is defined (Triangle()). It is automatically called when an object is created and prints “first constructor.”

  2. Parameterized Constructor:
    Accepts parameters during object creation to customize the initial state.
    Provides flexibility for objects to start with different values.
    Syntax: ClassName(type param1, type param2, …) { /* Initialization code */ }
    Example 2:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
                base = 0;
                height = 0;
            }
            //parameterized constructor
            Triangle(int b, int h)
            {
                base = b;
                height = h;
                cout << "parameterized constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height = h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob(5, 10);
        //ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }
    

    Parameterized Constructor:

    Accepts parameters (int b and int h) for custom initialization.
    Prints “parameterized constructor” when called.
    The parameterized constructor is employed during object creation, providing initial values for the base and height members.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;
class student {
    private:
        char name[20];
        int id;
    public:
        student()
        {
            strcpy_s(name, "no name");
            id = 0;
        }
        student(char n[], int i)
        {
            cout << "parameterized constructor\n";
            strcpy_s(name, n);
            id = i;
        }
        student(char n[])
        {
            strcpy_s(name, n);
        }
        void print()
        {
            cout << "name = " << name << endl;
            cout << "id = " << id << endl;
        }
};
int main()
{
    student ob("Mohammed", 1450902032);
    ob.print();

    return 0;
}

This code defines a class student representing a student with private member variables name and id. The class includes three constructors: an empty constructor, a parameterized constructor with both name and id, and a parameterized constructor with only the name. Let’s break down the code step by step:

– Class Definition: student

class student {
private:
    char name[20];
    int id;

public:
    // Empty Constructor
    student() {
        strcpy_s(name, "no name");
        id = 0;
    }

    // Parameterized Constructor (with name and id)
    student(char n[], int i) {
        cout << "parameterized constructor\n";
        strcpy_s(name, n);
        id = i;
    }

    // Parameterized Constructor (with name only)
    student(char n[]) {
        strcpy_s(name, n);
    }

    // Member Function to print student details
    void print() {
        cout << "name = " << name << endl;
        cout << "id = " << id << endl;
    }
};
  • Empty Constructor:
    Initializes name to “no name” and id to 0.
  • Parameterized Constructor (with name and id):
    Accepts parameters (char n[] and int i).
    Prints “parameterized constructor” when called.
    Sets name and id based on the provided values.
  • Parameterized Constructor (with name only):
    Accepts a parameter (char n[]).
    Initializes only the name attribute.
  • Member Function:
    print: Displays the student’s name and id.

– main Function:

int main() {
    // Object of class student created using the parameterized constructor with name and id
    student ob("Mohammed", 1450902032);

    // Printing the details of the student
    ob.print();

    return 0;
}
  • Object Creation:
    An object ob of type student is created using the parameterized constructor with both name and id.
  • Printing Details:
    The print member function is called to display the details of the student, including the name and id.

The output of this program would be:

parameterized constructor
name = Mohammed
id = 1450902032

This code illustrates the use of multiple constructors in a C++ class. Depending on the provided arguments during object creation, different constructors can be called to initialize the object accordingly.

3. Copy Constructor:

Example 4:

#include <iostream>
using namespace std;
class Copy {
    private:
        int a1, a2, a3, a4, a5, a6, a7, a8;
    public:
        Copy(int aa1, int aa2, int aa3, int aa4,
            int aa5, int aa6, int aa7, int aa8)
        {
            a1 = aa1;
            a2 = aa2;
            a3 = aa3;
            a4 = aa4;
            a5 = aa5;
            a6 = aa6;
            a7 = aa7;
            a8 = aa8;
        }
        Copy(const Copy &a)
        {
            a1 = a.a1;
            a2 = a.a2;
            a3 = a.a3;
            a4 = a.a4;
            a5 = a.a5;
            a6 = a.a6;
            a7 = a.a7;
            a8 = a.a8;
        }
        void print()
        {
            cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
                 << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
        }
};
int main()
{
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    g.print();
    Copy h(g);
    h.print();

    return 0;
}

This code defines a class Copy with two constructors – one for initializing an object with specific values and another for performing a deep copy of an existing object. Let’s break down the code:

– Class Definition: Copy

class Copy {
private:
    int a1, a2, a3, a4, a5, a6, a7, a8;

public:
    // Parameterized Constructor for Initialization
    Copy(int aa1, int aa2, int aa3, int aa4,
         int aa5, int aa6, int aa7, int aa8) {
        a1 = aa1;
        a2 = aa2;
        a3 = aa3;
        a4 = aa4;
        a5 = aa5;
        a6 = aa6;
        a7 = aa7;
        a8 = aa8;
    }

    // Copy Constructor for Deep Copy
    Copy(const Copy &a) {
        a1 = a.a1;
        a2 = a.a2;
        a3 = a.a3;
        a4 = a.a4;
        a5 = a.a5;
        a6 = a.a6;
        a7 = a.a7;
        a8 = a.a8;
    }

    // Member Function to Print Object Details
    void print() {
        cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
             << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
    }
};
  • Parameterized Constructor:
    Initializes the object with specific values provided as arguments.
  • Copy Constructor:
    Performs a deep copy of an existing object (Copy &a).
    Copies each member variable of the source object to the new object.
  • Print Function:
    Displays the values of the object’s member variables.

– main Function:

int main() {
    // Creating an object 'g' and initializing it with specific values
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    
    // Printing the details of object 'g'
    g.print();

    // Creating another object 'h' and initializing it by performing a deep copy of 'g'
    Copy h(g);

    // Printing the details of object 'h'
    h.print();

    return 0;
}
  • Object Creation (g):
    An object g of type Copy is created and initialized with specific values.
  • Printing Details (g):
    The print member function is called to display the details of object g.
  • Object Creation (h):
    Another object h is created and initialized by performing a deep copy of object g using the copy constructor.
  • Printing Details (h):
    The print member function is called to display the details of object h

The output of this program would be:

1 2 3 4 5 6 7 8 
1 2 3 4 5 6 7 8 

This code illustrates the usage of a copy constructor to create a new object with the same values as an existing object, ensuring a deep copy of the data.

Destructor

What is a Destructor?

In C++, a destructor is a special member function that is automatically called when an object goes out of scope or is explicitly deleted. Its primary purpose is to clean up resources or perform actions before the object’s memory is deallocated.

Destructor Charachteristics:

  1. Name and Syntax:
    Name: Destructors have the same name as the class, preceded by a tilde (~).
    Syntax: ~ClassName()
  2. Automatic Invocation:
    Destructors are automatically invoked when an object goes out of scope or is explicitly deleted.
    They handle the cleanup and deallocation of resources held by the object.
  3. No Return Type or Parameters:
    Destructors don’t have a return type, not even void.
    They do not accept any parameters.
  4. Single Destructor per Class:
    Each class can have only one destructor.
    It’s responsible for cleaning up resources allocated during the object’s lifetime.
  5. Manual Deletion:
    For objects created dynamically using new, the destructor is called explicitly using delete.
    This is essential for releasing memory allocated on the heap.
  6. Resource Cleanup:
    Destructors are often used to release resources such as dynamic memory, file handles, database connections, etc.
    Ensures proper cleanup before the object is destroyed.

Why Use Destructors?

Destructors are essential for proper resource management and maintaining the integrity of your program. They are particularly useful when dealing with dynamic memory allocation, file handling, or any situation where cleanup is necessary.

Syntax of a Destructor:

The syntax for a destructor is straightforward. It has the same name as the class preceded by a tilde (~). Here’s an example:

class MyClass {
public:
    // Constructor
    MyClass() {
        // Constructor code
    }

    // Destructor
    ~MyClass() {
        // Destructor code
    }
};

Example 1:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(int a, int b)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}

This code defines a class Rectangle representing a rectangle with private member variables W (width) and H (height). The class includes a constructor for creating a rectangle and a destructor for cleaning up resources when the rectangle is deleted. Let’s break down the code:

– Class Definition: Rectangle

class Rectangle {
private:
    int W, H;

public:
    // Constructor
    Rectangle(int a, int b) {
        W = a;
        H = b;
        cout << "A rectangle has been created\n";
    }

    // Destructor
    ~Rectangle() {
        cout << W << " " << H << " A rectangle has been deleted\n";
    }
};
  • Constructor:
    Initializes the W (width) and H (height) member variables with the values passed as arguments.
    Prints a message indicating that a rectangle has been created.
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

– main Function:

int main() {
    // Creating two objects of class Rectangle
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}
  • Object Creation:
    Two objects, R1 and R2, of type Rectangle are created in the main function.
  • Constructor Execution:
    The constructor of the Rectangle class is executed for each object, initializing their width and height.
    Messages are printed indicating that rectangles have been created.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for R1 and R2 are automatically called.
    Messages are printed indicating that rectangles have been deleted, along with their dimensions.

The output of this program would be:

A rectangle has been created
A rectangle has been created
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

This output demonstrates the automatic invocation of the constructor when objects are created and the destructor when objects go out of scope (at the end of the program in this case). The destructor prints messages indicating the deletion of rectangles along with their dimensions.

Example 2:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(): W(0), H(0)
        {
            cout << "W = " << W << " H = " << H << endl;
        }
        Rectangle(int a, int b): W(0), H(0)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
            Rectangle ob;
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);
    Rectangle R3;

    return 0;
}
  • Default Constructor:
    Initializes W and H to 0.
    Prints the initial values of W and H when an object is created with this constructor.
  • Parameterized Constructor:
    Accepts parameters a and b to set the dimensions of the rectangle.
    Initializes W and H to 0 before assigning the provided values.
    Prints a message indicating that a rectangle has been created.
    Creates another object ob inside the constructor (not recommended in general practice).
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

The output of this program would be:

A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
W = 0 H = 0
0 0 A rectangle has been deleted
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

Example 3:

#include <iostream>
using namespace std;
class phone {
    private:
        char name[10];
        char model[10];
        int price;
    public:
        phone() {}
        phone(char n[], char m[], int p)
        {
            strcpy(name, n);
            strcpy(model, m);
            price = p;
        }
        void print();
        ~phone();
};
phone::~phone()
{
    cout << "object destructed\n"
}
void phone::print()
{
    cout << "Name = " << name << endl;
    cout << "Model = " << model << endl;
    cout << "Price = " << price << endl;
}
int main()
{
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();
    return 0;
}

This code defines a class phone representing a phone with private member variables name, model, and price. The class includes a default constructor, a parameterized constructor, a member function (print), and a destructor. Let’s break down the code:

– Class Definition: phone

class phone {
private:
    char name[10];
    char model[10];
    int price;

public:
    // Default Constructor
    phone() {}

    // Parameterized Constructor
    phone(char n[], char m[], int p) {
        strcpy(name, n);
        strcpy(model, m);
        price = p;
    }

    // Member Function to Print Phone Details
    void print();

    // Destructor
    ~phone();
};
  • Default Constructor:
    An empty default constructor is provided.
  • Parameterized Constructor:
    Accepts parameters n (name), m (model), and p (price) to initialize the object’s member variables.
  • Member Function (print):
    Displays the details of the phone, including its name, model, and price.
  • Destructor:
    Outputs a message when an object of the class is destructed.

– Destructor Implementation:

phone::~phone() {
    cout << "object destructed\n";
}

The destructor is defined outside the class and prints a message when an object of the class is destructed.

– main Function:

int main() {
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();

    return 0;
}
  • Object Creation:
    Two objects, ob1 and ob2, of type phone are created.
    ob2 is initialized using the parameterized constructor.
  • Printing Details:
    The print member function is called for ob2 to display its details.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for ob1 and ob2 are automatically called.
    A message is printed indicating that an object has been destructed.

The output of this program would be:

Name = HUAWI
Model = MATE 9
Price = 400
object destructed

This output demonstrates the creation, printing, and destruction of phone objects, including the use of the parameterized constructor and the destructor.

Example 4:

#include <iostream>
#include <cstring>
using namespace std;
class Student {
    private:
        char name[20];
        int ID;
    public:
        Student()
        {
            cout << "Object created\n";
        }
        ~Student()
        {
            cout << "Object destructed\n";
        }
        void Set_Name_ID(char n[], int id)
        {
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
}; //end of class definition
void F(Student S)
{
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
int main()
{
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Funcrion\n";
    St1.print();
    return 0;
}

This code defines a class Student representing a student with private member variables name and ID. The class includes a default constructor, a destructor, a member function to set the name and ID, and another member function to print the student’s details. Additionally, there is a function F that takes a Student object as a parameter and demonstrates object creation, assignment, modification, and destruction within a function. Let’s break down the code:

– Class Definition: Student

class Student {
private:
    char name[20];
    int ID;

public:
    // Default Constructor
    Student() {
        cout << "Object created\n";
    }

    // Destructor
    ~Student() {
        cout << "Object destructed\n";
    }

    // Member Function to Set Name and ID
    void Set_Name_ID(char n[], int id) {
        strcpy(name, n);
        ID = id;
    }

    // Member Function to Print Student Details
    void print(void) {
        cout << name << "\t" << ID << endl;
    }
};
  • Default Constructor:
    Prints a message indicating that an object has been created.
  • Destructor:
    Prints a message indicating that an object has been destructed.
  • Set_Name_ID Function:
    Accepts parameters n (name) and id (ID) to set the member variables.
  • print Function:
    Prints the name and ID of the student.

– Function F:

void F(Student S) {
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
  • Creates a Student object S1 within the function.
  • Copies the content of the parameter S into S1.
  • Modifies the content of S using the Set_Name_ID function.
  • Prints the details of both S and S1.

– main Function:

int main() {
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Function\n";
    St1.print();
    return 0;
}
  • Object Creation and Modification:
    Creates two Student objects, St1 and St2.
    Sets their names and IDs using the Set_Name_ID function.
  • Function Call:
    Calls the function F passing St1 as a parameter.
  • Object Destruction:
    Prints messages indicating the destruction of objects when they go out of scope (end of the function or program).

The output of this program would be:

Object created
Object created
Going to Function
Object created
Sami    12345
Ahmad   11111
Object destructed
Object destructed
Back from Funcrion
Ahmad   11111
Object destructed
Object destructed

This output demonstrates the creation, modification, and destruction of Student objects, including the behavior of the default constructor and destructor. The F function illustrates object copying and modification within a function.

Structure

Structures in C++ provide a powerful way to organize and store related data under a single name. They are a fundamental concept in Object-Oriented Programming (OOP) that allows you to create custom data types to suit your program’s needs. In this guide, we’ll delve into the basics of structures in C++.

What is a Structure?

A structure is a user-defined data type in C++ that enables you to group together different data types under a single name. This makes it easier to manage and organize related information. Unlike primitive data types, structures can hold a collection of variables with various data types.

Defining a Structure:

To create a structure, you use the struct keyword, followed by the structure’s name and a block of variables inside curly braces. Here’s a simple example:

// Define a structure named 'Person'
struct Person {
    char name[50];
    int age;
    float height;
};

In this example, we’ve created a structure named Person with three members: a character array for the name, an integer for age, and a float for height.

Accessing Structure Members:

You can access the members of a structure using the dot (.) operator.

Example 1:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
};

int main()
{
    car g;
    g.name = "Kia";
    g.color = "red";
    cout << g.name << endl; //Kia
    cout << g.color << endl;  //red

    return 0;
}

This code defines a simple program that utilizes a structure named car. The structure car has four members: name (string), color (string), maxspeed (integer), and model (integer). The program then declares a variable g of type car and assigns values to its name and color members. Finally, it prints the values of name and color to the console.

Initializing Structure Variables:

You can initialize structure variables at the time of declaration, similar to how you initialize primitive variables:

// Initialize structure variables
Person person3 = {"Alice", 30, 5.5};

Example 2:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
}g, k;

int main()
{
    k = {"aa", "black", 300, 97};
    g = {"kia", "red", 250, 96};
    cout << g.maxspeed << endl;

    return 0;
}

This code defines a structure named car with four members (name, color, maxspeed, and model). Additionally, it declares two structure variables, g and k, of type car. In the main function, it assigns values to these structure variables using an initialization syntax and then prints the value of the maxspeed member of the g structure variable. Here’s a detailed explanation:

– Structure Definition and Variable Declaration:

struct car {
    string name;
    string color;
    int maxspeed;
    int model;
} g, k;  // Declaration of structure variables g and k of type car

Defines a structure named car and declares two structure variables g and k of type car.

– Main Function:

int main() {
    // Initialization of structure variable k
    k = {"aa", "black", 300, 97};

    // Initialization of structure variable g
    g = {"kia", "red", 250, 96};

    // Print the value of the maxspeed member of the g structure variable
    cout << g.maxspeed << endl;

    return 0;
}

Execution Flow:

  1. Initialization of Variables:
    k = {“aa”, “black”, 300, 97}; initializes the members of structure variable k with the provided values.
    g = {“kia”, “red”, 250, 96}; initializes the members of structure variable g with the provided values.
  2. Print to Console:
    cout << g.maxspeed << endl; prints the value of the maxspeed member of the g structure variable to the console, followed by a newline.
  3. Return Statement:
    return 0; indicates that the program has executed successfully.

The output of this program would be:

250

Functions and Structures:

Structures can be passed as arguments to functions, allowing you to create more modular and organized code.

Example 3:

#include <iostream>
#include <string>
using namespace std;

struct Distance
{
    int feet;
    float inches;
};
Distance add_distance(Distance d1, Distance d2)
{
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

int main()
{
    Distance x, y, z;
    cout << "Enter feet value \n";
    cin >> x.feet >> y.feet;
    cout << "Enter inches value \n";
    cin >> x.inches >> y.inches;
    z = add_distance(x, y);
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

This code demonstrates the use of structures to represent distances in feet and inches. It defines a structure Distance with two members: feet (integer) and inches (float). The program then includes a function add_distance to add two distance structures, and the main function takes user input for two distances, adds them using the add_distance function, and prints the result. Here’s a step-by-step explanation:

– Structure Definition:

struct Distance {
    int feet;
    float inches;
};

Defines a structure named Distance with two members: feet (integer) and inches (float).

– Function to Add Distances:

Distance add_distance(Distance d1, Distance d2) {
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

Defines a function add_distance that takes two Distance structures as parameters, adds their corresponding feet and inches members, and returns a new Distance structure representing the sum.

– Main Function:

int main() {
    Distance x, y, z;

    // User input for the first distance (x)
    cout << "Enter feet value \n";
    cin >> x.feet;
    cout << "Enter inches value \n";
    cin >> x.inches;

    // User input for the second distance (y)
    cout << "Enter feet value \n";
    cin >> y.feet;
    cout << "Enter inches value \n";
    cin >> y.inches;

    // Add the two distances using the add_distance function
    z = add_distance(x, y);

    // Print the result
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

Execution Flow:

  1. User Input:
    The user is prompted to enter the feet and inches values for two distances (x and y).
  2. Function Call:
    The add_distance function is called with the x and y structures as arguments, and the result is stored in the z structure.
  3. Print to Console:
    The program prints the result, displaying the summed feet and inches of the distances.
  4. Return Statement:
    return 0; indicates that the program has executed successfully.

– Sample Execution:
If the user enters:

Enter feet value
3
Enter inches value
6.5
Enter feet value
2
Enter inches value
3.2

The program would output:

z.feet = 5 z.inches = 9.7

Example 4:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;

struct exam
{
    float first;
    float second;
    float final;
};
class subject
{
        char name[10];
        exam Exam;
    public:
        subject()
        {
            strcpy(name, "no name");
            Exam = {0, 0, 0};
        }
        subject(char n[], float fa, float s, float fi)
        {
            strcpy(name, n);
            Exam = {fa, s, fi};
        }
        float total()
        {
            return Exam.first + Exam.second + Exam.final;
        }
        void print()
        {
            cout << "The subject = " << name << endl
                 << "First Exam = " << Exam.first << endl
                 << "Second Exam = " << Exam.second << endl
                 << "Final Exam = " << Exam.final << endl
                 << "The Total is = " << total() << endl;
        }
};

int main()
{
    subject e("OOP", 25, 24, 49);
    e.print();
    return 0;
}

This code defines a program that uses a combination of structures and classes to model a subject with exam scores. Let’s break down the code step by step:

– Structure Definition:

struct exam {
    float first;
    float second;
    float final;
};

Defines a structure named exam with three members representing exam scores: first, second, and final.

– Class Definition:

class subject {
    char name[10];
    exam Exam;
public:
    // Default constructor
    subject() {
        strcpy(name, "no name");
        Exam = {0, 0, 0};
    }

    // Parameterized constructor
    subject(char n[], float fa, float s, float fi) {
        strcpy(name, n);
        Exam = {fa, s, fi};
    }

    // Member function to calculate the total exam score
    float total() {
        return Exam.first + Exam.second + Exam.final;
    }

    // Member function to print subject details
    void print() {
        cout << "The subject = " << name << endl
             << "First Exam = " << Exam.first << endl
             << "Second Exam = " << Exam.second << endl
             << "Final Exam = " << Exam.final << endl
             << "The Total is = " << total() << endl;
    }
};

Defines a class named subject with private members:

  • name: An array of characters representing the subject’s name.
  • Exam: An instance of the exam structure representing exam scores.

The class includes:

  • A default constructor (subject()) initializing name to “no name” and Exam to all zeros.
  • A parameterized constructor (subject(char n[], float fa, float s, float fi)) initializing name and Exam with provided values.
  • A total() member function calculating the total exam score.
  • A print() member function printing subject details.

– Main Function:

int main() {
    // Create an instance of the subject class
    subject e("OOP", 25, 24, 49);

    // Call the print() member function to display subject details
    e.print();

    return 0;
}

In the main function:

  • An instance e of the subject class is created using the parameterized constructor.
  • The print() member function is called on the e object, displaying the details of the subject and its exam scores.

– Sample Output:

The subject = OOP
First Exam = 25
Second Exam = 24
Final Exam = 49
The Total is = 98

This output represents the details of the “OOP” subject, including scores on the first, second, and final exams, as well as the total score.

 

New Delete

In object-oriented programming (OOP) with C++, pointers play a crucial role in managing memory and accessing objects dynamically. Here’s a brief explanation of pointers in the context of OOP in C++:

Definition:

A pointer is a variable that holds the memory address of another variable. In C++, pointers can be used to store addresses of objects created dynamically on the heap.

Example 1:

int main()
{
    int var1 = 11;
    int var2 = 22;
    cout << &var1 << endl;
    cout << &var2 << endl;
    
    int *ptr;
    ptr = &var2;
    *ptr = 5000;
    cout << *ptr << endl;
    cout << var2 << endl;
}

This code demonstrates the use of pointers to manipulate variables and access their memory addresses.

  1. Variable Declaration and Initialization:
    int var1 = 11;
    int var2 = 22;
    

    Two integer variables, var1 and var2, are declared and initialized with values 11 and 22, respectively.

  2. Printing Memory Addresses:
    cout << &var1 << endl;
    cout << &var2 << endl;
    

    The memory addresses of var1 and var2 are printed using the address-of operator (&). This reveals the locations in memory where these variables are stored.

  3. Pointer Declaration and Assignment:
    int *ptr;
    ptr = &var2;
    

    A pointer variable ptr of type int is declared. The address of var2 is assigned to the pointer ptr.

  4. Using Pointer to Modify Variable:
    *ptr = 5000;
    

    The value pointed to by ptr is changed to 5000. Since ptr points to the address of var2, this also modifies the value of var2.

  5. Printing Pointer Value and Modified Variable:
    cout << *ptr << endl;
    cout << var2 << endl;
    

    The value pointed to by ptr (5000) and the modified value of var2 are printed. Both values should be the same, as the pointer was used to modify the content of var2.

The output of the code might look like this:

0x7fff5fbff628  // Memory address of var1
0x7fff5fbff624  // Memory address of var2
5000             // Value pointed to by ptr
5000             // Modified value of var2

The exact memory addresses and values may vary depending on the system and compiler.

Dynamic Memory Allocation:

OOP often involves the creation of objects using the new operator for dynamic memory allocation. Pointers are used to store the address of the dynamically allocated objects.

Deleting Dynamic Objects:

When dynamic objects are no longer needed, they should be explicitly deleted to avoid memory leaks. The delete operator is used.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int *p;
    p = new int;
    *p = 10;
    cout << p << endl;
    delete p;
}

This code demonstrates dynamic memory allocation and deallocation for an integer variable. Here’s an explanation of the code:

#include <iostream>
using namespace std;

int main()
{
    // Declare a pointer variable
    int *p;

    // Allocate memory for an integer on the heap
    p = new int;

    // Assign a value to the dynamically allocated integer
    *p = 10;

    // Print the address of the dynamically allocated memory
    cout << p << endl;

    // Deallocate the dynamically allocated memory
    delete p;

    return 0;
}

Explanation:

  1. Pointer Declaration:
    int *p;
    

    Declares a pointer variable p that will be used to store the address of a dynamically allocated integer.

  2. Dynamic Memory Allocation:
    p = new int;
    

    Allocates memory on the heap to store an integer and assigns the address of the allocated memory to the pointer p.

  3. Assigning a Value:
    *p = 10;
    

    Dereferences the pointer p and assigns the value 10 to the dynamically allocated integer.

  4. Printing the Address:
    cout << p << endl;
    

    Prints the address of the dynamically allocated memory. This address is on the heap and may vary each time the program runs.

  5. Memory Deallocation:
    delete p;
    

    Deallocates the memory previously allocated with new. This step is crucial to prevent memory leaks.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    // Declare two pointer variables
    int *p1, *p2;

    // Allocate memory for the first integer on the heap
    p1 = new int;
    *p1 = 10;

    // Print the location of the pointer and the content of the allocated memory
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    // Allocate memory for the second integer on the heap
    p2 = new int;
    *p2 = 10;

    // Print the location of the second pointer and the content of the allocated memory
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;

    // Deallocate the dynamically allocated memory
    delete p1;
    delete p2;

    return 0;
}

This code demonstrates dynamic memory allocation for two integer variables using pointers. Here’s an explanation of the code:

  1. Pointer Declaration:
    int *p1, *p2;
    

    Declares two pointer variables, p1 and p2, which will be used to store the addresses of dynamically allocated integers.

  2. Dynamic Memory Allocation (p1):
    p1 = new int;
    *p1 = 10;
    

    Allocates memory on the heap for an integer using new, assigns the address to p1, and assigns the value 10 to the dynamically allocated integer.

  3. Printing Information (p1):
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    Prints the location of the pointer variable p1 and the content of the memory it points to.

  4. Dynamic Memory Allocation (p2):
    p2 = new int;
    *p2 = 10;
    

    Allocates memory on the heap for another integer using new, assigns the address to p2, and assigns the value 10 to the dynamically allocated integer.

  5. Printing Information (p2):
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;
    

    Prints the location of the pointer variable p2 and the content of the memory it points to.

  6. Memory Deallocation:
    delete p1;
    delete p2;
    

    Deallocates the dynamically allocated memory using delete to avoid memory leaks.

Example 4:

#include <iostream>
using namespace std;

class CRectangle 
{
        int *width, *height;
    public:
        CRectangle(int, int); //constructor
        ~CRectangle(); //destructor
        int area()
        {
            return (*width * *height);
        }
};
CRectangle::CRectangle(int a, int b)
{
    width = new int;
    height = new int;
    *width = a;
    *height = b;
}
CRectangle::~CRectangle()
{
    delete width;
    delete height;
}
int main()
{
    CRectangle rect(3, 4), rectb(5, 6);
    cout << "rect area: " << rect.area() << endl;
    cout << "rectb area: " << rectb.area() << endl;
    return 0;
}

This code defines a class CRectangle for rectangles using dynamic memory allocation for width and height. Here’s a breakdown of the code:

  1. Class Definition (CRectangle):
    The class CRectangle represents rectangles, with private members width and height stored as dynamic integer pointers.
  2. Constructor (CRectangle::CRectangle):
    The constructor allocates memory for width and height using new and initializes them with the provided values.
  3. Destructor (CRectangle::~CRectangle):
    The destructor deallocates the memory for width and height using delete.
  4. Member Function (area):
    The area function calculates and returns the area of the rectangle using the values stored in width and height.
  5. Main Function:
    Creates instances of CRectangle (rect and rectb) with dynamic memory allocation for width and height.
    Calls the area function to calculate and display the area of each rectangle.
    The destructors are automatically called when the instances (rect and rectb) go out of scope, freeing the dynamically allocated memory.

 

 

Array of object and Pointers to Objects

In the world of object-oriented programming (OOP) with C++, managing multiple objects efficiently is crucial. Two powerful concepts that help achieve this are Arrays of Objects and Pointers to Objects. This documentation will provide a clear understanding of both concepts and how they can be employed in C++.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};

    // Printing the memory address of the array (address of the first element)
    cout << arr << endl;

    // Printing the value at the first element of the array
    cout << *arr << endl;

    // Printing the memory address of the second element of the array
    cout << arr + 1 << endl;

    // Printing the memory address of the last element of the array
    cout << arr + 4 << endl;

    // Printing the value at the last element of the array
    cout << *(arr + 4) << endl;
    
    // Using a loop to print all elements of the array using pointer arithmetic
    for (size_t i = 0; i < 5; i++)
    {
        cout<< *(arr + i) << endl;
    }

    return 0;
}

This program demonstrates the use of pointers with arrays.

The output will display the memory addresses, values, and elements of the array based on the pointer arithmetic and loop iterations.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};
    int *p;
    p = arr;
    for (size_t i = 0; i < 5; i++)
    {
        cout << *p << endl;
        p++;
    }

    return 0;
}

This C++ program demonstrates the use of a pointer to iterate through an array.

The output will display the values of each element in the array, printed one at a time, as the pointer p is incremented within the loop.

10
50
40
77
33

Note:

  • The pointer p is initially set to the address of the first element of the array.
  • Incrementing the pointer (p++) makes it point to the next element in the array.
  • This approach provides an alternative way to iterate through array elements using pointers.

Example 3:

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Student
{
        char name[20];
        int ID;
    public:
        Student() //empty constructor
        {
            cout << "empty\n";
            strcpy(name, "No name");
            ID = 0;
        }
        Student(char n[], int id) //constructor overloading
        {
            cout << "parameterize\n";
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
};
int main()
{
    Student S1("Ali", 123), S2("Ahmad", 456);
    Student arr[3];
    for (int i = 0; i < 3; i++)
        arr[i].print();
    return 0;
}

This program demonstrates the use of constructor overloading and default constructors in a class Student. Let’s break down the code:

  1. Class Student:
    Defines a class named Student with private data members name and ID.
    Contains two constructors: an empty constructor and a parameterized constructor.
    Provides a member function print() to display student details.
  2. Empty Constructor:
    Student()
    {
        cout << "empty\n";
        strcpy(name, "No name");
        ID = 0;
    }
    

    Initializes name with “No name” and ID with 0.
    Prints “empty” when an object is created using this constructor.

  3. Constructor Overloading:
    Student(char n[], int id)
    {
        cout << "parameterize\n";
        strcpy(name, n);
        ID = id;
    }
    

    Initializes name and ID with the provided arguments.
    Prints “parameterize” when an object is created using this constructor.

  4. print() Function:
    void print(void)
    {
        cout << name << "\t" << ID << endl;
    }
    
    

    Prints the student’s name and ID.

  5. Creating Objects:
    Objects S1 and S2 are created using the parameterized constructor, displaying “parameterize” for each object.
    An array arr of Student objects is created using the default constructor, displaying “empty” for each object.
  6. Printing Student Details:
    The print() function is called for each object in the array to display their details.

Output:
The output will display the constructor messages and the details of each student in the array.

 

 

 

Enumeration

Introduction

In C++, an enumeration, also known as enumerated type, is a user-defined data type that consists of a set of named integer constants. These constants are essentially representative names assigned to integer values.

Declaration:

  • The enum keyword is used to declare an enumeration.
  • You list the constant names separated by commas, optionally enclosed in curly braces.
  • By default, constants start with a value of 0 and increment by 1 for each subsequent one.
  • You can explicitly assign specific integer values to individual constants.

Example 1:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
enum days {sat = 1, sun, mon, tue, wed, thu, fri};
int main()
{
    string d[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
    days m[7] = {sat, sun, mon, tue, wed, thu, fri};
    for (size_t i = 0; i < 7; i++)
    {
        cout << m[i] << " - " << d[i] << endl;
    }
    return 0;
}

Enumeration days:

  • Declares an enumeration named days to represent the days of the week.
  • Assigns values to each day: sat = 1, sun, mon, etc. (subsequent days get implicit values incremented from the previous one).

String Array d:

  • Creates an array of strings named d with a size of 7, holding the full day names (“sat”, “sun”, …, “fri”).

Enumeration Array m:

  • Creates an array of enumeration values named m with a size of 7, containing the day enumerations (sat, sun, …, fri).

for Loop:

  • Iterates through the elements of both d and m using a single index i.
  • For each iteration:
    – Prints the current enumeration value from m[i] followed by a hyphen (“-“).
    – Prints the corresponding day name from d[i] on the same line.

Example 2:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
string da[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
enum Days {sat = 1, sun, mon, tue, wed, thu, fri};
class week {
        Days d[7];
    public:
        void setday(Days w[])
        {
            for (size_t i = 0; i < 7; i++)
                d[i] = w[i];
        }
        void p()
        {
            for (size_t i = 0; i < 7; i++)
                cout << "The number of day " <<  da[i] << " = " << d[i] << endl;
        }
};
int main()
{
    Days d[7] = {sat, sun, mon, tue, wed, thu, fri};
    week g;
    g.setday(d);
    g.p();
    return 0;
}

Array da:

  • Declares a global string array da of size 7, storing the full day names (“sat”, “sun”, …, “fri”).

Enumeration Days:

  • Defines an enumeration named Days to represent the days of the week with integer values:
    – sat = 1
    – sun (implicitly 2)
    – mon (implicitly 3)
    – …
    – fri (implicitly 7)

Class week:

  • Represents a “week” concept.
    – Member variable:
    * d is an array of Days enumeration type, holding the numerical day values for a week (e.g., sat, sun, …).
    – Member methods:
    * setday(Days w[]): Takes an array of Days enumeration values as input and assigns them to the d member array, copying the day values into the object.
    * p(): Prints the day names and their corresponding numerical values from the d array. It iterates through the array, accessing both the current da string and the d value at the same index to print the pair.

main Function:

  • Creates an array d of Days type and initializes it with sat, sun, …, fri.
  • Instantiates a week object named g.
  • Calls the setday method of g to pass the d array (containing the day values) to the object.
  • Calls the p method of g, which prints the day information in the format “The number of day <day name> = <day value>”.

The code demonstrates the use of enumerations and classes to represent and manage day-of-the-week information in C++.

Static Class Member Static Member Function

Introduction

In C++, “static class members” and “static member functions” introduce class-level elements that are not associated with individual objects of the class.

#include <iostream>
#include <string>
using namespace std;
void f()
{
    static int x = 0;
    x++;
    cout << x << endl;
}
int main()
{
    f();
    f();
    return 0;
}

This C++ program defines a function f() that increments a static integer variable x each time it is called, and then prints the value of x to the standard output. The main() function calls f() twice.

Here’s what the program does:

  • The function f() is defined. It contains a static variable x initialized to 0.
  • Each time f() is called, it increments x by 1 and prints the new value of x.
  • In the main() function, f() is called twice.
  • When f() is called the first time, x is incremented from 0 to 1, and 1 is printed.
  • When f() is called the second time, x is incremented from 1 to 2, and 2 is printed.

Therefore, when you run the program, it should output:

1
2

Here’s what static does in this context:

  1. Preserves Value between Function Calls: When a variable is declared as static inside a function, its value persists between function calls. This means that the variable retains its value even after the function f() exits. In the example, the variable x retains its value between calls to f().
  2. Initialization: Static variables are initialized only once, at the start of the program execution. In this case, the static variable x is initialized to 0 the first time the function f() is called. Subsequent calls to f() do not reinitialize x.
  3. Storage Duration: Static variables have “static storage duration,” meaning they are allocated memory for the entire duration of the program’s execution. This memory is allocated in the data segment of the program.
  4. Scope: The scope of a static variable declared inside a function is limited to that function. It cannot be accessed from outside the function. In this example, x can only be accessed within the f() function.

Static Class Member

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
//define how many objects are created 
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            cout << "Numbers of students constructed: " << count << endl;
        }
}; //end of class
int Student::count = 0;
int main()
{
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

Class Definition (Student):

  • It defines a class Student with private data members name, first, second, final, total, and ID.
  • The count variable is declared as static within the class. This means it is shared among all instances of the Student class, and its value persists across multiple Student objects.

Constructor:

  • The class has a default constructor Student() which initializes the data members with default values.
  • In the constructor, the name is set to “No name”, ID is set to 0, and exam scores are set to 0.
  • Each time a Student object is constructed, the count variable is incremented, and the total number of constructed students is printed.

Static Member Initialization:

  • The count static member is initialized outside the class definition.

Main Function:

  • In the main() function, two Student objects (S1 and S2) are created using the default constructor. The program prints the number of students constructed after each object creation.
  • Then, an array St of three Student objects is created. Again, the program prints the number of students constructed after creating this array.

Output:

Construct 2 objects
Numbers of students constructed: 1
Numbers of students constructed: 2

Construct 3 objects
Numbers of students constructed: 3
Numbers of students constructed: 4
Numbers of students constructed: 5

The count static member variable is used to keep track of the total number of Student objects that have been created. Each time a Student object is constructed (i.e., when the constructor is called), the count is incremented. This allows the program to keep track of how many Student objects have been instantiated across the entire program execution.

Static Member Function

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        static void print_count()
        {
            cout << "Students constructed: " << count << endl;
        }
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            print_count();
        }
}; //end of class
int Student::count = 0;
int main()
{
    Student::print_count();
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

In this updated version of the program, a static member function print_count() has been added to the Student class. Here’s what the static keyword does in this context:

  • Static Member Function: The member function print_count() is declared as static. This means that it belongs to the class itself, rather than to individual instances (objects) of the class. Static member functions do not have access to non-static member variables or functions directly because they are not associated with any particular object.
  • Accessing Static Member Variables: Inside the static member function print_count(), the static member variable count is accessed directly. Since count is also static, it can be accessed without needing an instance of the class.
  • Accessing Static Member Function: Static member functions can be called using the class name followed by the scope resolution operator (::). For example, Student::print_count() calls the print_count() function of the Student class.
  • Usage: In the main() function, Student::print_count() is called before any Student objects are created. This demonstrates that static member functions can be called without the need for object instantiation.
  • Initialization and Increment: Inside the Student constructor, the count variable is incremented each time a new Student object is constructed. The print_count() function is called within the constructor to display the updated count after each object creation.

This program demonstrates the usage of a static member function to access a static member variable and provide functionality associated with the class itself, rather than individual objects of the class.

Constant Object Constant Member Function

Introduction

In C++, a constant variable is a variable whose value cannot be changed once it has been initialized. The value remains constant throughout the execution of the program. Constant variables are declared using the const keyword.

Constant Object

  • Declaration: A constant object is declared by using the const keyword along with the object’s type.
  • Immutable: Once declared as const, the member variables of the object cannot be changed.
  • Calling Member Functions: A constant object can only call constant member functions of its class. This prevents any operations that might modify the object’s internal state.

Constant Member Function

  • Declaration: A member function is declared as constant by appending the const keyword to its declaration and definition.
  • Promise Not to Modify: A constant member function implicitly promises not to modify any of the non-static data members of its class.
  • Enforce Correctness: This helps the compiler enforce correctness and prevents unintentional side effects.

Example

#include <iostream>
using namespace std;
class time {
    private:
        int h, m, s;
    public:
        void print() const //constant function
        {
            cout << "Time = " << h << ":" << m << s << endl;
        }
        time(int i, int j, int k)
        {
            h = i;
            m = j;
            s = k;
        }
};
int main()
{
    const time noon(12, 0, 0); //constant object
    noon.print();

    return 0;
}

In the provided code, both constant functions and constant objects play important roles:

Constant Function (print() const):

  • The member function print() is declared as const, making it a constant member function.
  • A constant member function ensures that it does not modify the state of the object it is called on. It promises not to modify any non-static member variables of the class.
  • In this code, the print() function is responsible for displaying the time stored in the time object. Since it does not modify the object’s state, it is declared as const.
  • By declaring print() as a constant member function, it allows constant objects to call this function.

Constant Object (const time noon(12, 0, 0)):

  • An object named noon of the class time is created and declared as const. This makes noon a constant object.
  • A constant object is an object whose state cannot be modified after initialization. Any attempt to modify its state will result in a compilation error.
  • In this code, the noon object represents a specific time, 12:00:00, and it cannot be changed once created.
  • Constant objects are useful when you want to ensure that the object’s state remains unchanged throughout its lifetime, providing guarantees of immutability and safety.
  • By declaring noon as a constant object, it ensures that the print() function, which is also marked as const, can be called on it. This allows the print() function to access the noon object’s state without fear of modification.

In summary, the constant function (print() const) ensures that it does not modify the object’s state, and the constant object (const time noon(12, 0, 0)) guarantees that its state remains unchanged throughout its lifetime. These concepts work together to enforce immutability and safety in the code.

Friend Function/Friend class

In C++, a friend function or friend class is a feature that allows a function or a class to access private and protected members of another class. This feature breaks encapsulation to some extent but can be useful in specific scenarios where tight coupling between classes is necessary or when implementing certain design patterns.

Friend Function:

A friend function is a regular function that is granted access to private and protected members of a class. To declare a function as a friend of a class, you need to declare it within the class declaration preceded by the friend keyword.

Example 1:

#include <iostream>
using namespace std;
class myClass {
        int a, b;
    public:
        myClass(int i, int j)
        {
            a = i;
            b = j;
        }
        friend int sum(myClass ob);
};
int sum(myClass ob)
{
    return ob.a + ob.b;
}
int main()
{
    myClass o(10, 20);
    cout << sum(o) << endl;
    return 0;
}

In this C++ code snippet, a class called myClass is defined with two private integer members a and b. The class also has a constructor to initialize these members. Additionally, There is a declared friend function sum inside the class.

The sum function takes an object of type myClass as its argument and returns the sum of the private members a and b of that object.

In the main function, There is an object o of type myClass with initial values of 10 and 20, and then a call to the sum function passing this object o as an argument. Finally, the output of the result of the sum function using cout.

Here’s the breakdown of the code execution:

  1. An object o of type myClass is created with values 10 and 20.
  2. The sum function is called with the object o as an argument.
  3. Inside the sum function, the private members a and b of the object ob are accessed due to the friend declaration, and their sum is returned.
  4. The returned sum is then printed using cout.

So, when you run this program, it should output:

30

Example 2:

#include <iostream>
using namespace std;
class CRectangle {
    private:
        int width, height;
        friend CRectangle duplicate(CRectangle);
    public:
        void set_values(int, int);
        int area(void)
        {
            return (width * height);
        }
};
void CRectangle::set_values(int a, int b)
{
    width = a;
    height = b;
}
CRectangle duplicate(CRectangle R)
{
    CRectangle T;
    T.width = R.width * 2;
    T.height = R.height * 2;
    return T;
}
int main()
{
    CRectangle rect, rectb;
    rect.set_values(2, 3);
    cout << "The area before duplicate = " << rect.area() << endl;
    rectb = duplicate(rect);
    cout << "The area after duplicate = " << rectb.area() << endl;
    return 0;
}

This C++ code defines a class CRectangle representing a rectangle. The class has private data members width and height, and two member functions set_values and area.

In the private section, width and height are the dimensions of the rectangle. The set_values function is used to set the values of width and height. The area function calculates and returns the area of the rectangle.

The duplicate function is declared as a friend of CRectangle. This means it has access to the private members of CRectangle.

The set_values function sets the width and height of the rectangle based on the provided parameters.

The duplicate function takes a CRectangle object as a parameter, creates a new CRectangle object T, and assigns T’s width and height to be twice that of the input R’s width and height. It then returns the new rectangle T.

In the main function:

  1. CRectangle objects rect and rectb are created.
  2. rect’s set_values function is called to set its dimensions to 2×3.
  3. The area of rect before duplication is printed.
  4. duplicate function is called with rect as an argument, and the returned rectangle is assigned to rectb.
  5. The area of rectb after duplication is printed.

The output of this program will be:

The area before duplicate = 6
The area after duplicate = 24

Example 3:

#include <iostream>
using namespace std;
class Tri;
class CRectangle {
        int width, height;
    public:
        void set_values(int a, int b) {
            width = a;
            height = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
class Tri {
        int W, H;
    public:
        Tri(int a, int b)
        {
            W = a;
            H = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
int Sum(Tri T, CRectangle R)
{
    return T.W + R.width;
}
int main()
{
    CRectangle r;
    r.set_values(2, 3);
    Tri l(5, 10);
    cout << Sum(l, r) << endl;
    return 0;
}

This C++ code demonstrates the usage of friend functions across different classes. Here’s a breakdown of the code:

Class Declarations:

  • Two classes are declared: CRectangle and Tri.
  • CRectangle has two private data members width and height, and a member function set_values to set these values.
  • Tri has two private data members W and H, and a constructor to initialize them.

Friend Function Declaration:

  • Both classes declare a friend function named Sum. This means that Sum function can access the private members of both CRectangle and Tri.

Friend Function Implementation:

  • The Sum function takes objects of types Tri and CRectangle as arguments and returns the sum of their corresponding private members.
  • In this case, it returns the sum of W from the Tri object and width from the CRectangle object.

Main Function:

  • In the main function, an object r of type CRectangle is created and its set_values function is called to set its dimensions to 2×3.
  • Another object l of type Tri is created with dimensions 5×10.
  • The Sum function is called with objects l and r as arguments, and the result is printed.

Output:

  • Since the Sum function returns the sum of W from Tri and width from CRectangle, the output would be 5 + 2 = 7.

Friend Class:

Friend class is a class that is granted access to the private and protected members of another class. You declare a friend class by preceding its declaration with the friend keyword inside the class that it’s a friend of.

Example 4:

#include <iostream>
using namespace std;
class CSquare;
class CRectangle {
        int width, height;
    public:
        int area(void) {
            return (width * height);
        }
        void convert(CSquare);
};
class CSquare {
    private:
        int side;
    public:
        void set_side(int x)
        {
            side = x;
        }
        friend class CRectangle;
};
void CRectangle::convert(CSquare a)
{
    width = a.side;
    height = a.side;
}
int main()
{
    CSquare sqr;
    CRectangle rect;
    sqr.set_side(4);
    rect.convert(sqr);
    cout << rect.area() << endl;
    return 0;
}

This C++ code demonstrates the usage of friend classes and member functions, particularly in the context of a CRectangle class and a CSquare class.

Class Declarations:

  • Two classes are declared: CRectangle and CSquare.
  • CRectangle has two private data members width and height, and a member function area to calculate its area. It also has a member function convert, which is later defined outside the class.
  • CSquare has one private data member side and a member function set_side to set its value. It declares CRectangle as a friend class.

Friend Class Declaration:

  • CSquare declares CRectangle as a friend class, allowing CRectangle to access its private members.

Member Function Definition:

  • The convert member function of CRectangle is defined outside of the class.
  • It takes a CSquare object as a parameter and assigns its side to both width and height of the CRectangle.

Main Function:

  • In the main function, objects sqr of type CSquare and rect of type CRectangle are created.
  • set_side function of sqr sets its side to 4.
  • convert function of rect is called with sqr as an argument, converting the square into a rectangle.
  • The area of the resulting rect is then printed.

Output:

  • Since the side of the square is 4, after converting it to a rectangle, both width and height of the rectangle become 4. Therefore, the area of the resulting rectangle is 4 * 4 = 16.

Operator Overloading

Operator overloading in C++ is a feature that allows you to redefine the behavior of operators (such as +, -, *, /, etc.) for user-defined types. It enables you to extend the functionality of operators to work with objects of your own classes.

Example 1:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        void add(triangle c1, triangle c2)
        {
            width = c1.width + c2.width;
            height = c1.height + c2.height;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3.add(c1, c2);
    c3.showdata();
    return 0;
}

This C++ code defines a class triangle representing a triangle. The class has private data members width and height, a constructor to initialize them, member functions getdata to input values for width and height, showdata to display the width and height, and add to add two triangles together.

Class Definition:

  • The triangle class is defined with private data members width and height.
  • It has a constructor that initializes width and height with default values of 0.
  • It contains member functions getdata, showdata, and add.

Main Function:

  • In the main function, three triangle objects are created: c1, c2, and c3.
  • c1 is initialized with default values using the default constructor.
  • c2 is initialized with values 3.5 and 1.5 using the parameterized constructor.
  • c3 is created without any initialization.
  • getdata is called for c1 to input values for width and height.
  • add is called for c3 with c1 and c2 as arguments, which adds the corresponding width and height of c1 and c2 and assigns the result to c3.
  • showdata is called for c3 to display the resulting width and height after addition.

Example 2:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle add(triangle c2)
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1.add(c2);
    c3.showdata();
    return 0;
}

In this example, the addition of two triangles is also performed using a member function named add. However, instead of modifying the object on which the function is called, a new triangle object is created inside the add function to store the result of the addition. This new object is then returned from the function, leaving the original objects unchanged.

Example 3:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle operator+(triangle c2) // Overloading the + operator
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1 + c2;  // Using the overloaded + operator
    c3.showdata();
    return 0;
}

This C++ code demonstrates the usage of operator overloading to perform addition between two triangle objects. Let’s break down the code and highlight the differences compared to the previous examples:

Differences compared to previous examples:

  1. Operator Overloading:
    In this example, the + operator is overloaded using a member function named operator+. This allows us to perform addition between two triangle objects using the + operator in a manner similar to built-in types.
    In contrast, the previous examples used member functions (add) to perform addition between objects.
  2. Usage in main Function:
    In the main function, the addition of c1 and c2 is performed using the + operator: c3 = c1 + c2;.
    This syntax is more intuitive and concise compared to calling a separate member function (add).
  3. Return Type:
    The operator+ function returns a triangle object representing the result of the addition.
    In the previous examples, the add functions did not return any value and instead modified one of the objects directly.

this Pointer

In object-oriented programming (OOP) languages like C++, the this pointer is a keyword that is used to refer to the current object within a member function. It is a special pointer that holds the memory address of the current object instance.

Example 1:

#include <iostream>
using namespace std;
class stud {
    public:
        void address() {
            cout << this;
        }
};
int main()
{
    stud a, b, c;
    cout << "The adress of a\t";
    a.address();
    cout << endl << "The adress of b\t";
    b.address();
    cout << endl << "The adress of c\t";
    c.address();
    cout << endl;
    return 0;
}

In this C++ code, we have a class named stud, which contains a member function address(). This member function simply prints the memory address of the current object using the this pointer.

Function of this Pointer:

  • In the address() function of the stud class, this refers to the current object for which the member function is being called.
  • Inside the address() function, cout << this; prints the memory address of the current object.
  • In the main() function, we create three objects a, b, and c of the class stud.
  • We then call the address() function on each object, which prints the memory address of each object.
  • The this pointer ensures that the correct memory address of the current object is printed when address() function is called for each object.

Example 2:

#include <iostream>
using namespace std;
class Student {
        int id;
    public:
        void set_id(int id) {
            this->id = id;
        }
        void print_id() {
            cout << "ID is " << id << endl;
        }
};
int main()
{
    Student St;
    St.set_id(10);
    St.print_id();
    return 0;
}

In this C++ code, we have a class named Student with a private member variable id representing the student’s ID. The class provides two member functions: set_id() and print_id().

Function of this Pointer:

  • In the set_id() member function, the parameter id passed to the function has the same name as the member variable id of the class. To distinguish between them, the this pointer is used.
  • Inside the set_id() function, this->id = id; assigns the value of the parameter id to the member variable id of the current object.
  • The this pointer points to the current object for which the member function is called. It is used to access members of the object.
  • In the main() function, an object St of the class Student is created. The set_id() function is called to set the ID of the St object to 10.
  • Then, the print_id() function is called to print the ID of the St object.

The output of the code will be:

ID is 10

 

Operator Overloading/Unary operator

In C++, operator overloading refers to the ability to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Unary operators are those operators that operate on a single operand. Overloading unary operators allows you to customize their behavior when applied to objects of your own classes.

Purpose of Operator Overloading:

  1. Provide Natural Syntax: Operator overloading allows you to use operators with user-defined types in a way that mimics their usage with built-in types. For example, you can add two objects of a class using the + operator, concatenate strings using the + operator, or increment an object using the ++ operator.
  2. Enhance Readability: By overloading operators, you can make your code more intuitive and readable, as it allows you to express operations in a natural and concise way.

Example 1:

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary. Let’s break down the code:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the unary ++ operator as a member function
    void operator++() {
        x++;
        y++;
    }
};

int main() {
    Unary v(10, 20);
    v++; // Incrementing the object 'v' using overloaded ++ operator
    v.show(); // Displaying the updated values of 'x' and 'y'

    return 0;
}

Explanation:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded using the operator++() member function. This function increments the values of x and y.
  • In the main() function, an object v of the Unary class is created with initial values 10 for x and 20 for y.
  • The ++ operator is applied to the object v using v++. Since it’s a unary operator, it doesn’t require any operand.
  • The overloaded operator++() function increments the values of x and y by one.
  • After the increment operation, the show() function is called to display the updated values of x and y.

The output of the code will be:

11 21

This is because the values of x and y are incremented by 1 after the ++ operator is applied to the object v. Thus, the updated values are displayed as 11 for x and 21 for y.

Example 2:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
};
int main()
{
    Unary v(10, 20), k;
    v++;
    k = v++;
    k.show();
    v.show();

    return 0;
}

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary, along with the postfix increment operator ++ that takes an additional dummy integer parameter. Let’s break down the code:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded twice:
    1. The operator++() function overloads the prefix ++ operator. It increments the values of x and y and returns the updated object.
    2. The operator++(int) function overloads the postfix ++ operator with an additional dummy integer parameter. It creates a temporary object t and assigns the current object’s values to it. Then, it increments the values of x and y of the current object and returns the temporary object t.
  • In the main() function, two objects v and k of the Unary class are created, with v initialized with values 10 for x and 20 for y.
  • v++ is applied to increment v using the postfix increment operator. This will increment the values of x and y of v and return a temporary object with the original values.
  • k = v++ will first assign the temporary object (with original values) to k and then increment v using the postfix increment operator.
  • The show() function is called to display the values of k and v after the increment operations.

The output of the code will be:

11 21
12 22

Example 3:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the prefix ++ operator
    Unary operator++() {
        x++;
        y++;
        return *this;
    }

    // Overloading the postfix ++ operator with an additional dummy integer parameter
    Unary operator++(int) {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }

    // Overloading the unary - operator
    Unary operator-() {
        x = -x;
        y = -y;
        return *this;
    }
};

int main() {
    Unary k(1, 2); // Create an object of the class Unary with initial values 1 and 2
    -k; // Applying unary - operator to object k
    k.show(); // Display the updated values of k

    return 0;
}
  • The operator-() function overloads the unary – operator. It negates the values of x and y by multiplying them by -1 and returns the updated object.
  • In the main() function, an object k of the Unary class is created with initial values 1 for x and 2 for y.
  • The unary – operator is applied to the object k using -k. This will negate the values of x and y of k.
  • Finally, the show() function is called to display the updated values of x and y.

This indicates that the values of x and y of object k have been negated by applying the unary – operator. Therefore, x becomes -1 and y becomes -2.

Example 4:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
};
int main()
{
    Unary x(1, 1);
    if (!x)
        cout << "true";
    else
        cout << "false";

    return 0;
}
  • The operator!() function overloads the logical negation operator !. It returns true if both x and y are equal to 0, indicating that the object is logically false. Otherwise, it returns false.
  • In the main() function, an object x of the Unary class is created with initial values 1 for x and 1 for y.
  • The logical negation operator ! is applied to the object x using !x. If x is logically false (i.e., both x and y are 0), it prints “true”. Otherwise, it prints “false”.

The output of the code will be:

false

Example 5:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
    Unary operator+=(Unary b2)
    {
        x += b2.x;
        y += b2.y;
        return *this;
    }
};
int main()
{
    Unary b(1, 2), b2(3, 3);
    b += b2;
    b.show();
    
    return 0;
}

the operator+=() function overloads the compound assignment operator +=. It adds the corresponding member variables of the current object (this) with the member variables of the passed object (b2) and returns the updated object.

The output of the code will be:

4 5

 

Operator Overloading/Relational Operator

In C++, operator overloading allows you to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Relational operators are used to compare values between two operands and determine the relationship between them. Operator overloading for relational operators allows you to define custom comparison behaviors for objects of your own classes.

Purpose of Operator Overloading for Relational Operators:

  1. Custom Comparison: With operator overloading, you can define custom comparison behaviors for objects of your classes. This allows you to compare objects based on specific criteria relevant to your application domain.
  2. Natural Syntax: Overloaded relational operators enable you to use the familiar syntax of relational operators (<, <=, >, >=, ==, !=) with user-defined types. This improves code readability and makes your code more intuitive.

Example:

#include <iostream>
using namespace std;
class Relational {
        int x, y, z;
    public:
        Relational()
        {
            x = y = z = 0;
        }
        Relational(int i, int j, int k)
        {
            x = i;
            y = j;
            z = k;
        }
        int operator==(Relational b)
        {
            return(x == b.x && y == b.y && z == b.z);
        }
};
int main()
{
    Relational a(10, 10, 10), b(10, 10, 10);
    if (a == b)
        cout << "The two objects are equal\n";
    else
        cout << "The two objects are not equal\n";
    
    return 0;
}

This C++ code demonstrates operator overloading for the equality (==) operator in the Relational class.

  • The Relational class represents objects with three integer attributes x, y, and z.
  • The class provides two constructors: one default constructor that initializes all attributes to 0, and another constructor that allows initializing the attributes with provided values.
  • The operator= = function is overloaded inside the class. It takes another Relational object b as a parameter and returns an integer indicating whether the attributes of the two objects are equal. It checks if the x, y, and z attributes of both objects are equal and returns 1 if they are, and 0 otherwise.
  • In the main() function, two Relational objects a and b are created, both initialized with the values (10, 10, 10).
  • The overloaded equality operator == is used to compare objects a and b. If the attributes of both objects are equal, the message “The two objects are equal” is printed; otherwise, the message “The two objects are not equal” is printed.

STL C++

The Standard Template Library (STL) encompasses a collection of C++ template classes designed to furnish essential programming data structures and functionalities, including lists, stacks, arrays, and more. This library comprises container classes, algorithms, and iterators, making it a versatile toolset. STL’s components are parameterized, contributing to its generality. Proficiency in working with template classes is a prerequisite for effectively utilizing STL.

Introduction to Standard Template Library

The Standard Template Library (STL) is a powerful collection of classes and functions in C++ that provides reusable, generic algorithms, containers, and iterators. It’s an essential component of modern C++ programming and offers a wealth of functionality to simplify and enhance your code.

Key Components of STL:

  1. Containers:
    Containers are objects that store collections of other objects. They provide a way to organize and manipulate data efficiently. STL provides several container classes, each with its unique characteristics:
    – Vector: Dynamic array that automatically adjusts its size.
    – List: Doubly linked list that allows for fast insertions and deletions anywhere in the list.
    – Deque: Double-ended queue that supports fast insertion and deletion at both ends.
    – Set: Collection of unique, sorted elements.
    – Map: Collection of key-value pairs, where each key is unique.
    – Stack: Container with Last-In-First-Out (LIFO) access.
    – Queue: Container with First-In-First-Out (FIFO) access.
  2. Iterators:
    Iterators are objects that allow traversal through the elements of a container. They act as pointers and provide a uniform way to access the elements regardless of the underlying container implementation. There are different types of iterators:
    – Input iterators: Allow reading elements from a container.
    – Output iterators: Allow writing elements to a container.
    – Forward iterators: Support forward traversal.
    – Bidirectional iterators: Support bidirectional traversal (forward and backward).
    – Random access iterators: Support random access to elements (e.g., accessing elements by index).
  3. Algorithms:
    Algorithms are functions that operate on containers through iterators. They perform various operations such as searching, sorting, modifying, and manipulating elements in containers. STL provides a wide range of algorithms for common tasks, including:
    – Sorting: Sort elements in a container.
    – Searching: Search for elements in a container.
    – Transforming: Modify elements in a container based on certain criteria.
    – Copying: Copy elements between containers.
    – Merging: Merge elements from multiple containers into one sorted container.
    And many more…

Types of Container

  1. Simple
    – Pair
  2. Sequence
    – Array
    – Vector
    – Deque
    – List
    – Forward list
  3. Associative
    – Map
    – Multimap
    – Set
    – Multiset
  4. Unordered
    – Unordered set
    – Unordered multiset
    – Unordered map
    – Unordered multimap
  5. Adapter
    – Stack
    – Queue
    – Priority queue

Vector Part 1

Sequence containers in C++ are a category of containers within the Standard Template Library (STL) that store elements in a sequential order. They provide dynamic storage allocation and support various operations for accessing, inserting, and removing elements. Sequence containers are primarily categorized based on how they organize and manage their elements. Here’s an explanation of the commonly used sequence containers:

Arrays

Arrays are considered as a kind of sequence container in C++. However, they are typically categorized separately from other sequence containers like vectors, lists, and deques because of their fixed size nature and the absence of dynamic resizing capabilities.

Vector

Characteristics:

  1. Fast insert/ remove at the end
  2. Slow insert/ remove at the beginning or in the middle
  3. Slow search

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(4);
    v[0] = 10;
    v.push_back(50);

    return 0;
}

This code snippet attempts to create a vector of integers with an initial size of 4 elements, assigns a value to the first element, and then tries to add an additional element using the push_back function. However, there’s a potential issue with the usage of push_back after specifying the initial size.

Let’s analyze the code and discuss the implications:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(4);  // Creates a vector with 4 elements, all initialized to 0

    v[0] = 10;          // Assigns a value of 10 to the first element of the vector

    v.push_back(50);    // Attempts to add an additional element with the value 50
                        // This line may lead to undefined behavior because it's 
                        // appending an element beyond the originally specified size

    return 0;
}

Explanation:

  • The line vector<int> v(4); creates a vector v with an initial size of 4 elements, all initialized to the default value of integers (which is 0).
  • Then, v[0] = 10; assigns a value of 10 to the first element of the vector.
  • However, the subsequent line v.push_back(50); attempts to add an additional element to the vector using push_back. Since the vector was initially sized to contain only 4 elements, appending an element beyond this size may cause undefined behavior. The push_back operation might trigger a reallocation of the vector’s underlying storage, which could lead to memory corruption or other unexpected behavior.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4};  // Initialize vector v with values 1, 2, 3, 4
    vector<int>v2(v);             // Initialize vector v2 as a copy of v
    cout << v2[0];                // Output the first element of v2

    return 0;
}

This code snippet initializes a vector v with four integers {1, 2, 3, 4}, and then attempts to initialize another vector v2 as a copy of v.
The output will be 1, as it prints the first element of v2, which is a copy of v. Therefore, it will print the first element of v, which is 1.

Example 3:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100. This constructor initializes v with 5 elements, each having the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200. This constructor initializes v2 with 6 elements, each having the value 200.
  • cout << v2[0] << endl; prints the first element of v2, which is 200, followed by a newline character.

So, the output of this code will be:

200

Example 4:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    v.swap(v2);               // Swap the contents of v and v2
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200.
  • v.swap(v2); exchanges the contents of v and v2, effectively swapping the elements and sizes of the two vectors.
  • cout << v2[0] << endl; attempts to print the first element of v2.

However, after the swap operation, v2 now contains the elements originally in v, and v contains the elements originally in v2. Therefore, attempting to access v2[0] will actually print the first element of the vector that was initially v.

So, the output of this code will be:

100

Example 5:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v;           // Create an empty vector

    v.push_back(10);         // Add 10 to the end of the vector
    v.push_back(20);         // Add 20 to the end of the vector
    v.push_back(30);         // Add 30 to the end of the vector

    cout << v.front() << endl;  // Output the first element of the vector
    cout << v.back() << endl;   // Output the last element of the vector
    cout << v.at(0) << endl;    // Output the element at index 0 of the vector

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v;: Declares an empty vector of integers.
  • v.push_back(10);: Appends the value 10 to the end of the vector v.
  • v.push_back(20);: Appends the value 20 to the end of the vector v.
  • v.push_back(30);: Appends the value 30 to the end of the vector v.
  • cout << v.front() << endl;: Outputs the first element of the vector v using the front() member function. In this case, it prints 10.
  • cout << v.back() << endl;: Outputs the last element of the vector v using the back() member function. In this case, it prints 30.
  • cout << v.at(0) << endl;: Outputs the element at index 0 of the vector v using the at() member function. In this case, it prints 10.

So, the output of this code will be:

10
30
10

Example 6:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(100);   // Create a vector with 100 elements, all initialized to 0

    v.push_back(5);       // Append the value 5 to the end of the vector
    cout << "Size = " << v.size() << endl;        // Output the current size of the vector
    cout << "Capacity = " << v.capacity() << endl; // Output the current capacity of the vector

    return 0;
}

Here’s what each line does:

  • vector<int> v(100);: Creates a vector v with an initial size of 100 elements, all initialized to the default value of int, which is 0.
  • v.push_back(5);: Appends the value 5 to the end of the vector. Since the vector was initialized with a size of 100, but only one element was added, the vector will resize itself as needed to accommodate the new element.
  • cout << “Size = ” << v.size() << endl;: Outputs the current size of the vector using the size() member function. In this case, it prints 101, as there are now 101 elements in the vector.
  • cout << “Capacity = ” << v.capacity() << endl;: Outputs the current capacity of the vector using the capacity() member function. The capacity represents the maximum number of elements that the vector can hold without reallocating memory. In this case, it depends on the implementation, but it’s likely to be greater than or equal to 101, as the vector may allocate additional memory to avoid frequent reallocations when more elements are added.

Example 7:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4, 5};
    for (size_t i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {1, 2, 3, 4, 5};: Initializes a vector v with five elements, each containing the values 1, 2, 3, 4, and 5, respectively.
  • for (size_t i = 0; i < v.size(); i++) { … }: This is a traditional for loop that iterates over each element of the vector. It starts with an index i of 0 and continues until i is less than the size of the vector (v.size()).
  • size_t is an unsigned integer type used for representing sizes of objects. It’s commonly used for indices and sizes of containers like vectors.
  • cout << v[i] << ” “;: Within the loop, it prints the value of the element at index i of the vector, followed by a space.

So, the output of this code will be:

1 2 3 4 5

It prints each element of the vector v separated by a space.

 

Deque

Characteristics:

  1. Fast insert/ remove at the beginning and at the end
  2. Slow insert/ remove at the middle
  3. Slow research

List

Characteristics:

  1. Fast insertion and removal of elements from anywhere in the container
  2. Fast random access is not supported. It’s slow at accessing items from the middle
  3. Slow search
  4. Doubly-linked list

Forward List

Characteristics:

  1. First insertion and removal of elements from anywhere in the container
  2. Fast random access isn’t supported
  3. Singly-linked list

Vector Part 2

Iterators

In C++, iterators are objects that provide a way to traverse the elements of a container (such as vectors) in a sequential manner. Iterators act as pointers to elements in the container, allowing you to access and manipulate the elements efficiently. They serve as a bridge between algorithms and data structures, enabling you to perform various operations on container elements without needing to know the underlying implementation details.

For vectors specifically, iterators offer several functionalities:

  1. Accessing Elements: You can use iterators to access individual elements of a vector. Iterators support dereferencing, which allows you to retrieve the value of the element they point to.
  2. Traversal: Iterators provide mechanisms for traversing through the elements of a vector sequentially. You can increment or decrement an iterator to move to the next or previous element, respectively.
  3. Range-Based Operations: Iterators can define ranges within a vector, allowing you to perform operations on subsets of elements. For example, you can specify a range of iterators to indicate a subset of elements to sort or to copy to another container.
  4. Iterator Categories: Iterators in C++ are classified into different categories based on their capabilities and behavior. For vectors, the most commonly used iterator category is the random access iterator, which supports efficient random access to elements using arithmetic operations like addition and subtraction.
  5. Iterator Invalidation: Modifying a vector (e.g., inserting or erasing elements) can invalidate iterators pointing to elements within the vector. It’s essential to be aware of iterator invalidation rules to avoid undefined behavior when working with iterators.

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.begin();
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {10, 20, 30, 40};: Initializes a vector v with four integers {10, 20, 30, 40}.
  • vector<int>::iterator it = v.begin();: Declares an iterator it of type vector<int>::iterator and initializes it to point to the beginning of the vector v using the begin() member function.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the first element of the vector) and prints it using cout.

It prints the value of the first element of the vector v, which is 10.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.end()-1;
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int>::iterator it = v.end() – 1;: Declares an iterator it of type vector<int>::iterator and initializes it to point to the last element of the vector v by subtracting 1 from the result of the end() member function. Note that end() returns an iterator pointing to the position after the last element, so subtracting 1 points it to the last element.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the last element of the vector) and prints it using cout.

It prints the value of the last element of the vector v, which is 40.

Example 3:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over each element of the vector using an iterator it. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator is equal to v.end(), which represents one position past the end of the vector. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
20
30
40

Example 4:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int>v = {10, 20, 30, 40};

for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
{
cout << *it << endl;
}

return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using reverse iterators. It starts with the reverse iterator it pointing to the last element of the vector (v.rbegin()) and continues until the reverse iterator reaches the position before the first element (v.rend()), exclusive. In each iteration, the reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

40
30
20
10

Example 5:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using const reverse iterators. It starts with the const reverse iterator it pointing to the last element of the vector (v.crbegin()) and continues until the const reverse iterator reaches the position before the first element (v.crend()), exclusive. In each iteration, the const reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v in reverse order, starting from 40 and ending with 10.

Example 6:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++) { … }: This is a for loop that iterates over the vector elements using const iterators. It starts with the const iterator it pointing to the first element of the vector (v.cbegin()) and continues until the const iterator reaches the position after the last element (v.cend()), exclusive. In each iteration, the const iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v on a new line, iterating through the entire vector.

Auto

In C++, the auto keyword is used for type inference, allowing the compiler to automatically deduce the type of a variable based on its initializer. When used with vectors, auto can simplify code by automatically determining the correct type of iterators or elements without explicitly specifying it.

Using auto with vectors can make the code more concise and readable, especially when the iterator or element type is complex or when it’s changed frequently. However, it’s essential to use auto judiciously and ensure that the deduced type is clear and unambiguous.

Example 7:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {5, 10, 15, 20};  // Initialize vector v with four integers

    auto it = v.begin();  // Use auto to deduce the type of the iterator

    // Iterate over the vector elements using the deduced iterator type
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output the value pointed to by the iterator, followed by a newline
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {5, 10, 15, 20};: Initializes a vector v with four integers {5, 10, 15, 20}.
  • auto it = v.begin();: Uses auto to deduce the type of the iterator it. In this case, it deduces that it is of type vector<int>::iterator, pointing to the beginning of the vector v.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using the deduced iterator type. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
10
15
20

Example 8:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.insert(v.begin()+1, 12);
    v.insert(v.end()-1, 17);
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.insert(v.begin() + 1, 12);: Inserts the value 12 into the vector v at the position after the first element (index 1).
  • v.insert(v.end() – 1, 17);: Inserts the value 17 into the vector v at the position before the last element. Since v.end() points to one past the last element, subtracting 1 positions the insertion point before the last element.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
12
10
15
17
20

Example 9:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin());: Removes the first element from the vector v using the erase() method. Since v.begin() points to the first element, this operation removes that element from the vector.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
15
20

Example 10:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin()+1, v.end());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin() + 1, v.end());: Removes elements from the second element (index 1) until the end of the vector using the erase() method with iterators defining the range. The range is specified from v.begin() + 1 (the iterator pointing to the second element) to v.end() (the iterator pointing one past the last element).
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the remaining vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last remaining element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the remaining element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5

Example 11:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(10);
    
    for (int i = 0; i <10; i++)
        v[i] = i;
    
    cout << "Vector size initially: " << v.size();
    cout << "\nVector elemens are: ";
    for (int i = 0; i <10; i++)
        cout << v[i] << " ";
        
    v.resize(5);
    cout << "\n\nVector size after resize(5): " << v.size();
    v.shrink_to_fit();
    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(10);: Initializes a vector v with size 10, containing default-initialized elements (all elements are initialized to zero in this case).
  • Assigns values to the elements of the vector using a loop.
  • Outputs the initial size of the vector using v.size().
  • Outputs the elements of the vector using a loop.
  • Resizes the vector to size 5 using v.resize(5). This operation reduces the size of the vector to 5, and any excess elements are removed from the vector.
  • Outputs the size of the vector after resizing.
  • Calls v.shrink_to_fit() to reduce the capacity of the vector to match its size.

Note: shrink_to_fit() is a non-binding request to reduce the capacity of the vector to fit its size but does not guarantee that the capacity will actually be reduced. The implementation may choose to ignore the request.

 

Vector Part 3

Example 1:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5);  // Initialize vector v with size 5
    int n = 0;

    // Prompt the user to enter vector elements
    cout << "Enter Vector Elements:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cin >> v[i];  // Read input into vector element at index i
        
        // Check if we're at the end of the vector
        if (i == v.size() - 1) {
            cout << "If you want to resize the list, enter the new size. Enter -1 to finish: ";
            cin >> n;
            if (n == -1)
                break;
            else
               v.resize(n);  // Resize the vector to the new size entered by the user
        }
    }

    // Output the elements of the vector
    cout << "Vector elements are:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cout << v[i] << endl;  // Output each element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(5);: Initializes a vector v with size 5, containing default-initialized elements (all elements are initialized to zero in this case).
  • Prompts the user to enter vector elements.
  • Reads input from the user into the vector elements using a loop. After reading the last element, the code prompts the user to either resize the vector or exit the loop by entering -1.
  • If the user enters a new size, the vector is resized accordingly using v.resize(n).
  • Outputs the elements of the vector after the loop ends.

This code allows the user to dynamically resize the vector during input and then displays the elements of the vector.

Example 2:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some unsorted integers

    sort(v.begin(), v.end());  // Sort the elements of the vector in ascending order

    // Output the sorted elements of the vector
    for (auto it : v) {
        cout << it << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in an unsorted order.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm. The sort function requires two iterators specifying the range to be sorted, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).
  • for (auto it : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in ascending order.
  • cout << it << endl;: Within the loop, it prints each element it of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
3
5
7

It prints each element of the sorted vector v in ascending order, one element per line.

Example 3:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    sort(v.rbegin(), v.rend());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}

Here’s what each part of the code does:

  • sort(v.rbegin(), v.rend());: Sorts the elements of the vector v in descending order using the std::sort algorithm with reverse iterators. The sort function requires two iterators specifying the range to be sorted, which are v.rbegin() (pointing to the last element, treated as the first for sorting) and v.rend() (pointing to one before the first element, treated as the last for sorting).

So, the output of this code will be:\

7
5
3
2
1
0

It prints each element of the sorted vector v in descending order, one element per line.

Example 4:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    reverse(v.begin(), v.end());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}
  • reverse(v.begin(), v.end());: Reverses the elements of the vector v using the std::reverse algorithm. The reverse function requires two iterators specifying the range to be reversed, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).

So, the output of this code will be:

3
0
7
2
1
5

It prints each element of the reversed vector v, one element per line.

Example 5:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find and output the minimum element in the vector
    cout << *min_element(v.begin(), v.end()) << endl;

    // Find and output the maximum element in the vector
    cout << *max_element(v.begin(), v.end()) << endl;

    // Find and output the minimum element in the vector excluding the last two elements
    cout << *min_element(v.begin(), v.end() - 2) << endl;

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in the given order.
  • cout << *min_element(v.begin(), v.end()) << endl;: Finds the minimum element in the vector v using the std::min_element algorithm. The min_element function returns an iterator pointing to the minimum element, and * dereferences this iterator to obtain the value of the minimum element. The minimum element is then printed followed by a newline.
  • cout << *max_element(v.begin(), v.end()) << endl;: Similar to above, this line finds and prints the maximum element in the vector v.
  • cout << *min_element(v.begin(), v.end() – 2) << endl;: Finds the minimum element in the vector v excluding the last two elements. The range used for finding the minimum element is from v.begin() to v.end() – 2 (excluding the last two elements). The minimum element is then printed followed by a newline.

So, the output of this code will be:

0
7
1

It prints the minimum element, maximum element, and minimum element excluding the last two elements of the vector v, each followed by a newline.

Example 6:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};

    auto pair = minmax_element(v.begin(), v.end());
    cout << *pair.first << endl;
    cout << *pair.second << endl;

    return 0;
}

Here’s what each part of the code does:

  • auto pair = minmax_element(v.begin(), v.end());: Finds both the minimum and maximum elements in the vector v using the std::minmax_element algorithm. This function returns a pair of iterators, where the first iterator points to the minimum element and the second iterator points to the maximum element.
  • cout << *pair.first << endl;: Outputs the value of the minimum element by dereferencing the iterator pair.first.
  • cout << *pair.second << endl;: Outputs the value of the maximum element by dereferencing the iterator pair.second.

So, the output of this code will be:

0
7

It prints the minimum and maximum elements of the vector v, each followed by a newline.

Example 7:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find the minimum element in the vector
    auto it = min_element(v.begin(), v.end());

    // Sort the elements of the vector up to (but not including) the minimum element
    sort(v.begin(), it);

    // Output the sorted elements of the vector
    for (auto i : v) {
        cout << i << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • auto it = min_element(v.begin(), v.end());: Finds the minimum element in the vector v using the std::min_element algorithm. This function returns an iterator pointing to the minimum element.
  • sort(v.begin(), it);: Sorts the elements of the vector v up to (but not including) the minimum element found by min_element. It uses the std::sort algorithm with a range specified by iterators, from v.begin() to it. This sorts the elements before the minimum element.
  • for (auto i : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in sorted order.
    cout << i << endl;: Within the loop, it prints each sorted element i of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
5
7

It prints each element of the vector v up to the minimum element, sorted in ascending order, each followed by a newline.

Example 8:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool GreaterThanThree(int i) {
    return i > 3;
}

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Sort the elements of the vector in ascending order
    sort(v.begin(), v.end());

    // Find the first element greater than 3 using find_if with GreaterThanThree as the predicate
    auto it = find_if(v.begin(), v.end(), GreaterThanThree);

    // Output all elements greater than 3
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output each element greater than 3 followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • bool GreaterThanThree(int i): Defines a predicate function GreaterThanThree that returns true if the input integer i is greater than 3.
  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm.
  • auto it = find_if(v.begin(), v.end(), GreaterThanThree);: Finds the first element greater than 3 in the sorted vector v using the std::find_if algorithm with the GreaterThanThree predicate function.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the elements from the first element greater than 3 until the end of the vector. It outputs each element greater than 3 followed by a newline using cout.

So, the output of this code will be:

5
7

It prints each element of the vector v that is greater than 3, each followed by a newline.

Example 9:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool GreaterThanThree(int i)
{
    return i > 3;
}
int main()
{
    int arr[] = {10, 20, 30, 40, 50, 60, 70};
    vector<int> v(7);
    copy(arr, arr + 7, v.begin());
    cout << "myvector contains: ";
    for (auto it:v)
        cout << it << " ";
    return 0;
}

Here’s what each part of the code does:

  • int arr[] = {10, 20, 30, 40, 50, 60, 70};: Initializes a C-style array arr with seven integers.
  • vector<int> v(7);: Initializes a vector v with size 7.
  • copy(arr, arr + 7, v.begin());: Copies elements from the C-style array arr to the vector v using the std::copy algorithm. The copy function requires three parameters: the beginning and end iterators of the source range (here, arr and arr + 7 representing the whole array), and the beginning iterator of the destination range (here, v.begin()).
  • cout << “myvector contains: “;: Outputs a message indicating the start of the output.
  • for (auto it : v) cout << it << ” “;: This is a range-based for loop that iterates over the elements of the vector v. It outputs each element of the vector followed by a space.

So, the output of this code will be:

myvector contains: 10 20 30 40 50 60 70

Example 10:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    vector<int> to_vector(15);
    copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());
    cout << "to_vector contains: ";
    for (auto i: to_vector)
        cout << i << " ";
    return 0;
}

Here’s what each part of the code does:

  • vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};: Initializes a source vector from_vector with ten integers.
  • vector<int> to_vector(15);: Initializes a target vector to_vector with size 15.
  • copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());: Copies elements from the source vector from_vector to the target vector to_vector in reverse order using the std::copy_backward algorithm. The copy_backward function requires three parameters: the beginning and end iterators of the source range (here, from_vector.begin() and from_vector.end() representing the whole vector), and the end iterator of the destination range (here, to_vector.end()).
  • cout << “to_vector contains: “;: Outputs a message indicating the start of the output.
  • for (auto i : to_vector) cout << i << ” “;: This is a range-based for loop that iterates over the elements of the target vector to_vector. It outputs each element of the target vector followed by a space.

So, the output of this code will be:

to_vector contains: 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10

It prints each element of the target vector to_vector, which contains the elements of the source vector from_vector copied in reverse order, followed by a space. The initial elements of to_vector that were not overwritten by the copy operation are left unchanged (default-initialized to 0 in this case).

Example 11:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3, 4, 5};  // Initialize a vector v with five integers

    // Copy elements from the vector v to the standard output (cout)
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

Here’s what each part of the code does:

  • copy(v.begin(), v.end(), ostream_iterator<int>(cout, ” “));: Copies elements from the vector v to the standard output (cout) using the std::copy algorithm and std::ostream_iterator. The copy function requires three parameters: the beginning and end iterators of the source range (here, v.begin() and v.end() representing the whole vector), and the output iterator (here, ostream_iterator<int>(cout, ” “)) that writes each copied element to the standard output with a space separator.

So, the output of this code will be:

1 2 3 4 5

Properties of vector

  1. Add -> Back -> O(1):
    This line indicates that adding an element to the back (end) of a vector has a time complexity of O(1), meaning it’s a constant-time operation. Vectors have dynamic memory allocation, and adding an element to the back typically involves appending the element to the end of the underlying contiguous memory block, which can be done in constant time.
  2. Delete -> Back -> O(1):
    Deleting an element from the back (end) of a vector also has a time complexity of O(1), which means it’s a constant-time operation. Removing the last element usually involves decrementing the size of the vector, and no reallocation or shifting of elements is required.
  3. Add -> Any Where -> O(N):
    Adding an element anywhere except the back of the vector, such as at the front or in the middle, has a time complexity of O(N). This is because inserting an element at an arbitrary position may require shifting all subsequent elements to make room for the new element, which takes linear time proportional to the number of elements shifted.
  4. Delete -> Any Where -> O(N):
    Similarly, deleting an element from anywhere except the back of the vector also has a time complexity of O(N). Removing an element from an arbitrary position may require shifting all subsequent elements to fill the gap left by the deleted element, which also takes linear time proportional to the number of elements shifted.
  5. Access -> [] – at() -> O(1):
    Accessing an element in a vector by index using the square brackets ([]) operator or the at() member function has a time complexity of O(1). This means that accessing any element in the vector takes constant time regardless of the size of the vector. Vectors provide constant-time random access because they store elements in a contiguous memory block, allowing for direct access to any element by its index.
  6. Search -> find() -> O(log N):
    Searching for an element in a sorted vector using the std::find() algorithm has a time complexity of O(log N) when the vector is sorted. This is because std::find() performs a binary search on the sorted vector, which has a logarithmic time complexity. However, it’s important to note that if the vector is not sorted, the time complexity of finding an element using std::find() would be O(N), as it performs a linear search.

Advantages:

Implemented as dynamic arrays

Drawbacks:

  1. Expensive reallocation
  2. Requires Contiguous Memory

Data Structures

A data structure serves as a repository designed for the storage and structured organization of data, enabling efficient access and updates when utilized on a computer.

Complexity

Introduction:

Complexity in data structures is a fundamental concept in computer science that helps us analyze the performance and efficiency of algorithms. It allows us to quantify the resources (such as time and memory) required by an algorithm to solve a problem as the input size grows. In this article, we’ll explore the basics of complexity in data structures, including time complexity and space complexity, and how they impact algorithm design and analysis.

In search algorithms, analyzing the efficiency requires considering different potential scenarios. This helps us understand how the algorithm performs under different circumstances. Here, we’ll explore base case, average case, and worst case along with their complexity notation:

  1. Base Case (Omega notation):
    Denotes the simplest input where the algorithm terminates in the least number of steps.
    Notation: Varies depending on the algorithm. Often denoted by O(1) which signifies constant time, independent of input size.
  2. Average Case (Theta notation):
    Represents the performance expected on average when considering all possible inputs with equal probability.
    Notation: Depends on the algorithm’s design and data distribution. For example, linear search has an average case of O(n/2), meaning it takes half the comparisons, on average, to find an element in a list.
  3. Worst Case (Big O notation):
    Represents the most challenging scenario, requiring the maximum number of steps.
    Notation: Again, depends on the algorithm. Linear search’s worst case is O(n), signifying it may need to compare all elements if the target is not present or at the end.
  • Further Note:
    – Complexity notation uses symbols like O, Ω, and Θ to represent how the execution time grows with input size (Big O Notation, Big Omega Notation, and Big Theta Notation respectively).
    – These representations provide an idealized theoretical understanding of the algorithm’s efficiency, not always guaranteeing exact execution times.

Big O notation

Big O notation is a mathematical tool used in computer science to describe the upper bound of how an algorithm’s execution time or space complexity grows as the input size increases. In simpler terms, it helps us understand how efficiently an algorithm performs as it deals with larger and larger datasets.

Here are some key points about Big O notation:

What it describes:

Big O notation focuses on the limiting behavior of a function (usually representing the algorithm’s complexity) as the input size tends towards infinity. It ignores constants and lower-order terms, providing a general idea of the algorithm’s efficiency, not the exact execution time.

Key notations:

  • O(n): This is the most common notation, meaning the function grows linearly with the input size (n). Doubling the input roughly doubles the execution time. Examples include searching an unsorted list (linear search) and iterating through all elements of an array.
  • O(log n): This signifies logarithmic growth, which is much faster than linear. Doubling the input only increases the execution time by a constant amount. Binary search is a classic example.
  • O(1): This represents constant time complexity, meaning the execution time is independent of the input size. Accessing an element directly in an array by its index is O(1).
  • O(n^2): This denotes quadratic growth, where the execution time increases quadratically with input size. Nested loops can often lead to O(n^2) complexity.
  • O(k^n): This represents exponential growth, which is generally undesirable due to its rapid increase in execution time with even small input size.

Interpreting Big O:

  • Lower values (O(1), O(log n)) are generally better as they indicate faster algorithms that scale well with larger inputs.
  • Higher values (O(n^2), O(k^n)) can be problematic for large datasets as they lead to significant performance bottlenecks.

Big O is not the only complexity measure:

While Big O focuses on upper bounds, there are other notations like Omega (Ω) for lower bounds and Theta (Θ) for exact bounds.

Example 1:

sum; // n = 5
for (i = 1; i <= n; i++)
sum = sum + 1;

This code calculates the sum of numbers from 1 to n using a for loop. The loop iterates n times, and within each iteration, it performs a constant-time addition operation (sum = sum + 1).

Therefore, the time complexity of this code is O(n). This means that the execution time of the code grows linearly with the input size n. In other words, as the value of n increases, the time it takes for the code to run will also increase, but at a proportional rate.

Here’s a table summarizing the time complexity analysis:

Step Description Time Complexity
Initialization Declare variables sum and i O(1)
Loop Iterate n times O(n)
Increment Add 1 to sum in each iteration O(n)
Total O(n)

Overall, the code has a linear time complexity, which is considered efficient for many algorithms.

Introduction to Stack

Introduction:

In the realm of computer science and programming, understanding data structures is fundamental. One such essential data structure is the stack. In this article, we’ll delve into what stacks are, how they work, their operations, and their applications in programming.

What is a Stack?

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. Imagine a stack of plates in a cafeteria; you can only take the top plate off the stack. Similarly, in a stack data structure, elements can only be added or removed from the top.

How Does a Stack Work?

A stack has two primary operations: push and pop.

  • Push: Adds an element to the top of the stack.
  • Pop: Removes the top element from the stack.

Additionally, stacks typically support other operations like peek (to view the top element without removing it) and isEmpty (to check if the stack is empty).

Stack Implementation:

Stacks can be implemented using arrays or linked lists.

  • Array Implementation: In this approach, a fixed-size array is used to store the stack elements. Push and pop operations modify the top index of the array.
  • Linked List Implementation: Here, a linked list is used to implement the stack. Each node in the linked list represents an element, and the top of the stack is the head of the list.

Stack Operations:

Let’s look at the stack operations in detail:

  • Push: Adds an element to the top of the stack. The new element becomes the top element, and the stack size increases by one.
  • Pop: Removes the top element from the stack. The element is returned (or simply removed), and the stack size decreases by one.
  • getTop: Returns the top element of the stack without removing it.
  • isEmpty: Checks if the stack is empty. Returns true if the stack is empty, and false otherwise.

Applications of Stacks:

Stacks find applications in various areas of computer science and programming, including:

  • Function Call Stack: Used to manage function calls and local variables in programming languages.
  • Expression Evaluation: Used to evaluate arithmetic expressions, infix-to-postfix conversion, and solving postfix expressions.
  • Undo Mechanism: Supports the undo operation in text editors and graphic design software.
  • Backtracking: Used in algorithms like depth-first search (DFS) to explore all possible paths in a graph.

Conclusion:

In conclusion, stacks are simple yet powerful data structures that play a crucial role in many programming tasks. Understanding how stacks work and their applications can significantly enhance a programmer’s problem-solving abilities. Whether you’re a beginner or an experienced programmer, mastering stacks is essential for building efficient and robust software systems.

 

Stack Implementation

This code defines a simple stack class with basic operations like push, pop, getTop, and print. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

const int MAX_SIZE = 100;

class Stack {
private:
    int top;            // Index of the top element in the stack
    int item[MAX_SIZE]; // Array to store stack elements

public:
    // Constructor: Initializes top to -1 (empty stack)
    Stack() : top(-1) {}

    // Function to push an element onto the stack
    void push(int Element) {
        if (top >= MAX_SIZE - 1) {
            cout << "Stack is full on push" << endl;
        } else {
            top++;
            item[top] = Element;
        }
    }

    // Function to check if the stack is empty
    bool isEmpty() {
        return top < 0;
    }

    // Function to pop an element from the stack
    void pop() {
        if (isEmpty()) {
            cout << "Stack is empty on pop" << endl;
        } else {
            top--;
        }
    }

    // Function to get the top element of the stack
    void getTop(int& stackTop) {
        if (isEmpty()) {
            cout << "Stack is empty on getTop" << endl;
        } else {
            stackTop = item[top];
            cout << stackTop << endl;
        }
    }

    // Function to print the elements of the stack
    void print() {
        cout << "[";
        for (int i = top; i >= 0; i--) {
            cout << item[i] << " ";
        }
        cout << "]" << endl;
    }
};

int main() {
    Stack s;

    // Push elements onto the stack
    s.push(5);
    s.push(10);
    s.push(15);
    s.push(20);

    // Print the stack
    s.print();

    // Get and print the top element of the stack
    int y = 0;
    s.getTop(y);

    // Pop an element from the stack
    s.pop();

    // Push another element onto the stack
    s.push(7);

    // Print the stack again
    s.print();

    return 0;
}

Explanation:

  • The Stack class implements a stack using an array named item. It has member functions for push, pop, getTop, isEmpty, and print.
  • In the push function, if the stack is not full, it increments the top index and adds the element to the item array at the top index.
  • The isEmpty function checks if the stack is empty by comparing the top index with -1.
  • The pop function decrements the top index if the stack is not empty.
  • The getTop function retrieves the top element of the stack and stores it in the stackTop parameter.
  • The print function prints the elements of the stack from top to bottom.
  • In the main function, a Stack object s is created and various operations like push, pop, getTop, and print are performed on it, demonstrating the usage of the stack.

 

Stack Using Linked List(Linked Stack)-Part 1

Introduction

We’ve covered the concepts of a stack and a stack implemented using arrays. Now, let’s explore the implementation of a stack using pointers and discuss why it’s considered a superior approach.

You might be wondering why we need to discuss this alternative when we’ve already looked at stack implementations using arrays. Can’t we just stick to arrays?

The reason for exploring stack implementation with pointers is to address potential limitations we might encounter with array-based implementations, particularly regarding size constraints. By utilizing pointers, we can effectively circumvent such issues, ensuring a more flexible and robust solution for managing data within a stack structure.

Using pointers to implement a stack involves dynamically allocating memory for the stack elements and manipulating pointers to manage the stack structure. This approach is particularly useful when the size of the stack is not known beforehand or when memory efficiency is a concern.

Node Structure

A “node” refers to a fundamental building block used in many data structures, including linked lists, trees, graphs, and more. A node is a structure that contains two main components:

  1. Data: This component holds the actual value or element that the node represents. It could be of any data type depending on the application.
  2. Next Pointer (or Link): This component is a reference or pointer to the next node in the sequence. It establishes the connection between nodes in the data structure.

These code snippets define a basic node structure in different programming languages:

  • C++:
    struct Node {
        Type item;
        Node* next;
    };
    

    In C++, struct is used to define a structure named Node. It contains two members:

    – item: A variable of type Type to store data.
    – next: A pointer to another Node, indicating the next node in the sequence.

  • Java:
    class Node {
        Type item;
        Node next;
    }
    

    In Java, class is used to define a class named Node. Similarly, it has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • C#:
    class Node {
        Type item;
        Node next;
    }
    

    This is similar to Java. In C#, class is used to define a class named Node, and it also has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • Python:
    class Node:
        def __init__(self):
            self.item = None
            self.next = None
    

    In Python, a class named Node is defined. The __init__ method is a constructor used to initialize objects of the class. Inside the constructor:

    – self.item is initialized to None, indicating that it stores data.
    – self.next is initialized to None, indicating that it refers to the next node in the sequence.

stackTop

stackTop typically refers to the top element of a stack data structure. In the context of a stack, it is a variable or pointer that points to the topmost element of the stack, or in other words, the most recently added element.

To assign the value of stackTop to the next member of a node:

  • C++:
    newNode is a pointer to a node, and stackTop is presumably another pointer to a node. This line assigns the value of stackTop to the next pointer of the newNode, effectively linking newNode to the node pointed to by stackTop.

    newNode->next = stackTop;
    
  • Java, C#, Python:
    newNode is an object of type Node, and stackTop is also an object of type Node. This line assigns the reference of the object referred to by stackTop to the next field of the newNode.

    newNode.next = stackTop; // Java and C#
    
    newNode.next = stackTop // Python

To assigns the value of newNode to stackTop:
C++, Java, C#, Python:

stackTop = newNode

stackTop is a pointer to the top element of a stack implemented using pointers or dynamic memory allocation. stackTop = newNode would update stackTop to point to the newly created node newNode. This effectively makes newNode the new top element of the stack.
To creates a copy of stackTop we use the statement:

temp = stackTop

Why do we do that?

Creating a copy of stackTop (temp) allows you to safely manipulate and access the top element of the stack without affecting the original pointer, reference, or value. It provides flexibility and ensures that the original data remains intact for future use.

A Pointer-Base Implementation of the ADT Stack(linked stack) main Functions:

  • push(Type newItem)
  • pop()
  • pop(Type& stackTop)
  • getTop()
  • display()
  • isEmpty()

JAVA

Java is a high-level, versatile, and widely-used programming language known for its portability and flexibility. Originally developed by Sun Microsystems and now maintained by Oracle Corporation, Java has a vast ecosystem of libraries and tools that make it a popular choice for various software applications, from web development to mobile apps and enterprise-level systems. Java is appreciated for its ability to run on multiple platforms, its strong security features, and its support for object-oriented programming. It’s a key technology for building dynamic websites, interactive web applications, and mobile apps, making it a vital tool in the world of software development.

Introduction

Java Programming Language

Java is a class-based, object-oriented programming language. It is widely used for developing various types of applications, ranging from simple desktop utilities to complex enterprise-level systems.

Java is available for most operating systems (Write once run anywhere).

Applications of Java with Real-world Examples

  • Applications for Mobiles.
  • Desktop GUI Applications.
  • Web Applications.
  • Gaming Applications.
  • Enterprise Applications.
  • Security.
  • Scientific Applications.
  • Embedded Systems.
  • Big Data Technologies.
  • Distributed Applications.
  • Cloud-based Applications.
  • Web servers and Application servers.
  • Software Tools.

Why do we need to learn programming languages?

There are many reasons why learning a programming language like Java can be valuable, even if you don’t plan to become a professional programmer. Here are just a few:

  • Directly shape the digital landscape: Java is used to build countless websites and mobile apps, from your favorite social media platforms to online banking tools. Learning Java empowers you to be more than just a user; you can become a creator, shaping the digital experiences of others.
  • Boosts problem-solving and critical thinking: Programming helps you develop logical thinking skills and the ability to break down complex problems into smaller, solvable steps. This translates well to other areas of life, from tackling schoolwork to making everyday decisions.
  • Opens career doors: While not essential for every job, programming skills are increasingly sought-after across various industries. Even basic knowledge can give you an edge in many fields, from marketing and finance to data science and education.
  • It’s simply fun and rewarding! There’s a unique satisfaction in seeing your code come to life and create something functional or even beautiful. The learning process itself can be challenging and rewarding, fostering a sense of accomplishment and growth.

We also need to know how to communicate with computers, and to do so we have something called binary system which represents data and instructions using only two symbols: 0 and 1. This system is the foundation of digital computing because electronic devices, such as computers and microprocessors, interpret and process information in binary format.

As a programmer, you write source code to implement specific functions, such as generating text. This source code is written using a specific syntax. For example, in Java, you might write System.out.print(“Java”). This line of code is understandable to humans and is considered a high-level language representation.

However, before the machine can understand and execute this code, it must undergo several steps to translate it into a form it can process. Firstly, the code is passed through a Java compiler (javac), which checks the syntax and transforms the source code into bytecode. Bytecode is a low-level representation of the code that is platform-independent and can be executed by any system with a Java Virtual Machine (JVM).

Next, the bytecode is interpreted by the JVM, which acts as an interpreter. The JVM translates the bytecode into machine code instructions that the underlying operating system can understand and execute. This process allows Java programs to run on various operating systems without modification, making it a key feature of the Java language.

The Java Programming Language Platforms

  • Java Platform, Standard Edition (Java SE)
    – Desktop applications.
  • Java Platform, Enterprise Edition (Java EE)
    – Web applications, Server applications.
  • Java Platform, Micro Edition (Java ME)
    – Mobile applications, Gaming applications.
  • Java FX
    – Platform for desktop, mobile and embedded systems. Built on Java and fully featured toolkit for developing rich client applications.

Installing the Java Development Tools

Download Java Development Kit

To download Java Development Kit (JDK) for Java programming, follow these steps:

  1. Open your web browser and search for “download JDK for Java” on Google. Visit the official Oracle website because Java is owned by Oracle. You’ll be directed to the Java SE Downloads page.
  2. On the Java SE Downloads page, choose the JDK version that corresponds to your operating system. Options are typically available for Windows, macOS, and Linux.
  3. Accept the Oracle Technology Network License Agreement for Oracle Java SE to proceed with the download. Read through the terms and conditions and accept them if you agree.
  4. Click on the download link to start downloading the JDK installer file. The file format will be .exe for Windows, .dmg for macOS, and .tar.gz for Linux.
  5. Once the download is complete, locate the downloaded installer file and run it. Follow the on-screen instructions to install the JDK on your system.

Setting up development environment

Now, to set up your development environment:

  1. Download an Integrated Development Environment (IDE) for Java. Again, perform a Google search for “IDE for Java” and consider downloading Apache NetBeans, which is a user-friendly IDE for Java development. If you don’t want to download the ide you could work with us right now with an online compiler and we recommend ideone.com.
  2. Search for “download NetBeans for Java” on Google. Look for the Apache NetBeans release and download it.
  3. Once the download is complete, you can find the downloaded NetBeans IDE on your device. Navigate to the “Start” menu and click on it to open the NetBeans IDE.
  4. To start your first project in NetBeans, click on “File” > “New Project” > “Java” > “Java Application”. Choose a name for your project (e.g., “FirstProject”) and select your desired location. Click “Finish” to create the project.
  5. In the project window, navigate to the “Source Packages” folder. Right-click on the folder’s content and select “New” > “Java Class”. Name the class using capital letters for each word with no spaces (e.g., “NewClass”). Make sure the class name matches the name of the Java file. Click “Finish” to create the class.

By following these steps, you’ll have successfully downloaded and installed the JDK for Java development, set up the Apache NetBeans IDE, and created your first Java project. You’re now ready to start coding in Java!

Syntax Rules

Here are the rules of Java syntax:

  1. Reserved Words: Certain words in Java are reserved for specific purposes and cannot be used as identifiers (e.g., class, public, static). These words are known as reserved words or keywords and are highlighted in blue.
  2. Code Blocks: All code blocks in Java must be enclosed within curly brackets {}. This includes class definitions, method definitions, loops, and conditional statements.
  3. Main Method: The starting point of a Java program is the main method. It must be declared as public static void main(String[] args) and should always be written as shown below:
    public static void main(String[] args) {
        // Code goes here
    }
    
  4. Semicolons: Semicolons (;) are used to terminate statements in Java. Every statement must end with a semicolon.
  5. Example Program:
    public class MyFirstProgram {
        public static void main(String[] args) {
            System.out.print("Hello");
        }
    }
    

     

  6. The System.out.print() method is a function in Java that is used to display output to the console. Here’s a breakdown of its components:
    – System: System is a class in Java’s java.lang package. It provides access to the standard input, output, and error streams of the system.
    – out: out is a static member of the System class. It represents the standard output stream, which is typically the console or terminal where you see text output when running a Java program.
    – print(): print() is a method of the out object. It is used to display text or other data on the standard output stream without advancing to the next line. Whatever is passed as an argument to the print() method will be displayed on the console.
    For example:

    System.out.print("Hello");
    

    This line of code will display “Hello” on the console.

  7. Case Sensitivity: Java is case-sensitive, meaning that uppercase and lowercase letters are treated as distinct. For example, “hello” and “Hello” are considered different identifiers.

Types of Errors

In Java, errors can generally be categorized into three main types:

  1. Syntax Error: Syntax errors occur when the rules of Java syntax are violated. These errors are detected by the compiler during the compilation process. Common syntax errors include misspelled keywords, missing semicolons, and incorrect use of operators. Syntax errors prevent the program from being compiled successfully.
  2. Runtime Error: Runtime errors, also known as exceptions, occur during the execution of a program. These errors occur when unexpected conditions or situations arise while the program is running. Common examples include dividing by zero, accessing an array element out of bounds, and attempting to use a null object reference. Runtime errors cause the program to terminate abruptly unless they are handled using exception handling mechanisms such as try-catch blocks.
  3. Logical Error: Logical errors occur when the program does not produce the expected output due to incorrect logic or algorithmic errors in the code. Unlike syntax errors and runtime errors, logical errors do not cause the program to terminate or produce error messages. Instead, they result in incorrect behavior or output. Debugging logical errors often involves careful analysis of the code’s logic and algorithm to identify and fix the underlying issue.

Escape Sequences and Comments

Comments

In Java, comments are non-executable statements that are ignored by the compiler. They are used to provide explanations, documentation, and annotations within the code. There are three types of comments in Java:

  1. Single-line comments: Single-line comments begin with two forward slashes (//). Everything after // on the same line is considered a comment and is ignored by the compiler. Single-line comments are typically used for short explanations or comments on a single line of code.
    Example:

    // This is a single-line comment
    
  2. Multi-line comments: Multi-line comments, also known as block comments, are enclosed between /* and */. Everything between these symbols, including newlines, is considered a comment. Multi-line comments are often used for longer explanations or comments that span multiple lines of code.
    Example:

    /* This is a
       multi-line comment */
    
  3. Javadoc comments: Javadoc comments are a special type of comment used to generate documentation. They start with /** and end with */. Javadoc comments are used to describe classes, methods, and fields, and can include special tags to provide additional information such as parameters, return values, and exceptions.
    Example:

    /**
     * This is a Javadoc comment for the MyClass class.
     */
    public class MyClass {
        /**
         * This is a Javadoc comment for the myMethod method.
         * @param x This is a parameter of the method.
         * @return This method returns a value.
         */
        public int myMethod(int x) {
            return x * x;
        }
    }
    

Escape Sequences:

In Java, escape sequences are special character combinations used to represent characters that are difficult or impossible to represent directly in a string literal. Escape sequences are preceded by a backslash () character. Here are some common escape sequences used in Java:

  1. \n: Represents a newline character. When used within a string literal, it moves the cursor to the beginning of the next line.
  2. \t: Represents a tab character. When used within a string literal, it inserts a horizontal tab.
  3. \’: Represents a single quote character. Used to include single quote within a string literal.
  4. \”: Represents a double quote character. Used to include double quotes within a string literal.
  5. \\: Represents a backslash character. Used to include a backslash within a string literal.
  6. \r: Represents a carriage return character.
  7. \b: Represents a backspace character.
  8. \f: Represents a form feed character.

Example:

public class EscapeSequencesExample {
    public static void main(String[] args) {
        // Newline (\n) escape sequence
        System.out.println("Hello\nWorld"); // Output: Hello
                                            //         World
        
        // Tab (\t) escape sequence
        System.out.println("Java\tProgramming"); // Output: Java    Programming
        
        // Double quote (\") escape sequence
        System.out.println("She said, \"Hello!\""); // Output: She said, "Hello!"
        
        // Backslash (\\) escape sequence
        System.out.println("C:\\Users\\John\\Documents"); // Output: C:\Users\John\Documents
        
        // Carriage return (\r) escape sequence
        System.out.println("Overwritten text\r123"); // Output: 123written text
        
        // Backspace (\b) escape sequence
        System.out.println("Back\bspace"); // Output: Backspace
        
        // Form feed (\f) escape sequence
        System.out.println("Hello\fWorld"); // Output: Hello
                                             //         World

    }
}

 

Data Types

Naming Variables

In Java, variable names must adhere to certain standard rules to ensure clarity, readability, and compatibility with the language syntax. Here are the standard rules for naming variables in Java:

  1. Variable Name Length: Variable names can be of any length. However, it’s recommended to use meaningful and descriptive names while keeping them concise and readable.
  2. Valid Characters: Variable names can consist of letters (both uppercase and lowercase), digits, the underscore character (_), and the dollar sign ($). They must start with a letter, underscore, or dollar sign.
  3. Reserved Words: Variable names cannot be the same as Java keywords or reserved words. For example, you cannot name a variable “class” or “int” as they are reserved words in Java.
  4. Case Sensitivity: Java is case-sensitive, meaning uppercase and lowercase letters are treated as different characters. Therefore, “myVar” and “myvar” would be considered as two different variables.
  5. CamelCase Convention: It’s a common convention in Java to use CamelCase for naming variables. CamelCase involves writing compound words or phrases such that each word or abbreviation begins with a capital letter, with no spaces or punctuation between them. For example: myVariableName, totalAmount, studentAge.
  6. Meaningful Names: Variable names should be descriptive and convey the purpose or meaning of the variable. Avoid using single-letter variable names (except for loop counters) or overly cryptic abbreviations.
  7. Start with Lowercase: It’s a convention in Java to start variable names with a lowercase letter, except for constants, which are typically written in all uppercase.
  8. Special Characters: In addition to letters, digits, and underscore, you can use the dollar sign ($) as a special character in variable names. Avoid using other special characters like @, %, etc.

By adhering to these standard rules, you can create clear, concise, and meaningful variable names in Java code, promoting readability and maintainability.

Data Types

In Java, data types specify the type of data that can be stored in a variable. Java has two categories of data types: primitive data types and reference data types.

Primitive Data Types:

Primitive data types are the most basic data types in Java. They represent single values and are predefined by the language. There are eight primitive data types in Java:

  1. byte: Byte data type is an 8-bit signed two’s complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
  2. short: Short data type is a 16-bit signed two’s complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive).
  3. int: Int data type is a 32-bit signed two’s complement integer. It has a minimum value of -2^31 and a maximum value of 2^31-1.
  4. long: Long data type is a 64-bit signed two’s complement integer. It has a minimum value of -2^63 and a maximum value of 2^63-1.
  5. float: Float data type is a single-precision 32-bit IEEE 754 floating-point. It should never be used for precise values, such as currency.
  6. double: Double data type is a double-precision 64-bit IEEE 754 floating-point. It is used for decimal values that require more precision.
  7. boolean: Boolean data type represents one bit of information. It has only two possible values: true and false.
  8. char: Char data type is a single 16-bit Unicode character. It has a minimum value of ‘\u0000’ (0) and a maximum value of ‘\uffff’ (65,535 inclusive).

Example:

byte age = 25;
short distance = 10000;
int population = 1500000;
long nationalDebt = 20202020202020L; // Use 'L' suffix for long literals
float temperature = 32.5f; // Use 'f' suffix for float literals
double pi = 3.14159265359;
boolean isJavaFun = true;
char grade = 'A';

These primitive data types are the building blocks of Java programs, allowing developers to store and manipulate different types of data efficiently. Understanding their characteristics and appropriate usage is essential for writing effective Java code.

Note: There is srt which refers to string, but it is considered as an object data type.

OOP in JAVA

Object-Oriented Programming (OOP) is a fundamental programming paradigm used extensively in Java. In OOP, the core concept is organizing code into “objects,” which are instances of classes representing real-world entities, concepts, or data structures.

Introduction

Object-oriented programming

Object-oriented programming is a methodology or paradigm to design a program using classes and objects. It has many advantages like:

  • Reusability.
  • Readability.
  • Performance.
  • Space.

Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects. Java is a powerful and widely-used programming language that fully supports OOP principles.

Other languages that support OOP: Python, C++, Visual Basic, NET and Ruby.

There are other methodologies like:

  • Procedural programming that is used by C, Pascal, COBOL, FORTRAN, Java, Python, C++ ..etc.
  • Event-driven that is used by C#, Visual Basic, Visual C++ and Java.

Objects are fundamental building blocks in object-oriented programming (OOP) and play a crucial role in the design and implementation of systems. To illustrate this concept, let’s consider the example of designing a store system.

When we think about building a store system, the first thing that comes to mind is the objects involved. In this case, we can identify three main objects: products, customers, and payment methods.

Products: Products represent the items that the store sells. These could be anything from groceries to electronics or clothing. Each product in the store is characterized by its unique attributes such as name, price, quantity, and category. In OOP, products can be represented as objects with properties and behaviors. For example, we could have a Product class with attributes like name, price, and quantity, and methods to update product information or check availability.

Customers: Customers are individuals or entities who visit the store to purchase products. They interact with the store by browsing products, selecting items for purchase, and completing transactions. In OOP, customers can be modeled as objects with attributes such as name, address, contact information, and purchase history. We could have a Customer class with methods to place orders, view order history, or update personal details.

Payment Method: Payment methods are mechanisms used by customers to pay for their purchases. These could include cash, credit/debit cards, mobile wallets, or online payment gateways. Each payment method has its own set of rules and procedures for processing transactions. In OOP, payment methods can be represented as objects with properties and behaviors related to processing payments. We could define different payment method classes with methods to authorize payments, handle refunds, or generate transaction receipts.

By identifying these objects and their relationships, we can design a cohesive and modular store system that encapsulates the functionality of managing products, serving customers, and processing payments. Each object in the system encapsulates its own state and behavior, promoting encapsulation, modularity, and code reuse, which are key principles of object-oriented programming.

Objects

Objects in object-oriented programming (OOP) are composed of two essential members: data (properties, attributes) and operations (methods, functions, behaviors). These elements encapsulate the state and behavior of the object, respectively, and work together to represent real-world entities within a software system.

Let’s explore the car example to better understand these concepts:

  1. Attributes:
    Name: Represents the brand or manufacturer of the car.
    Max Speed: Indicates the maximum speed the car can achieve.
    Price: Denotes the cost or price of the car.
    Model: Represents the specific model or version of the car.
  2. Operations:
    move(): Represents the action of moving the car. This method may involve starting the engine, accelerating, braking, and steering.
    calculateVehicleAge(): Calculates the age of the car based on its manufacturing year or model year.
  3. Getters and Setters:
    get(): Getter methods retrieve the current value of an attribute.
    set(): Setter methods modify or update the value of an attribute.

For example, in the car class, we may have getter and setter methods for each attribute, such as getName() and setName() for the name attribute, getMaxSpeed() and setMaxSpeed() for the max speed attribute, and so on. These methods allow external code to access and modify the state of the car object in a controlled manner, promoting encapsulation and data integrity.

Additionally, the class diagram is a graphical representation of the structure and relationships of classes in a software system. It visually depicts the classes, their attributes, methods, and associations with other classes. Class diagrams provide a high-level overview of the system’s architecture and help developers understand the relationships between different components.

Classes

In object-oriented programming (OOP), a class is a blueprint or template that defines the structure and behavior of objects. It serves as a blueprint for creating objects with similar characteristics and functionalities. Classes encapsulate data (attributes) and operations (methods) into a single unit, providing a modular and reusable way to model real-world entities within a software system.

 

Classes and Objects

Creating a Class in Java using NetBeans:

Classes are like blueprints that define the structure and behavior of objects in Java. Think of them as templates for building specific objects with unique properties and abilities.

In Apache NetBeans, follow these steps to create a new class:

Project Setup:

  1. Go to File > New Project > Java Application.
  2. Name your project (e.g., JavaOOP) and click Finish.

Package Creation:

  1. Navigate to the Source Packages section.
  2. Click the + sign and choose New > Java Package.
  3. Name your package (e.g., com.mycompany.javaoop) and click Finish.

Class Creation:

  1. Right-click on the package you created.
  2. Select New > Java Class.
  3. Name your class (e.g., Main) and click Finish.

Code:

package com.mycompany.javaoop;

public class Main {
    public static void main(String[] args) {
        System.out.println("JAVA");
    }
}

Explanation of the Code:

– package com.mycompany.javaoop;: This line specifies the package where your Main class belongs. Organizing classes into packages helps maintain code structure and avoid naming conflicts.
– public class Main: This declares a public class named Main. Public classes can be accessed from other parts of your project.
– public static void main(String[] args): This is the main method, the entry point where your program execution begins.
– System.out.println(“JAVA”);: This line prints the string “JAVA” to the console.

Troubleshooting and Tips:

<No main classes found> Error: If you encounter this error, ensure you’ve set the Main Class field in your project’s Run configuration to com.mycompany.javaoop.Main.

Here’s how to address the “No main classes found” error in NetBeans:

  1. Right-click on the project name (in this case, “JavaOOP”) in the Projects window.
  2. Select Properties.
  3. Go to the Run category.
  4. In the Main Class field, enter the fully qualified name of your main class, including the package name. For example, if your class is named “Main” and it’s in the package “com.mycompany.javaoop”, you would enter com.mycompany.javaoop.Main.
  5. Click OK to save the changes.

Now try running your code again. It should execute without the “No main classes found” error.

Creating Classes and Objects:

Separate Files for Separate Classes: Each class in Java needs its own file, distinct from the Main class. This promotes organization and modularity in your code.

Creating the Car Class:

  1. Right-click on the package where you want to create the new class (e.g., com.mycompany.javaoop).
  2. Select New > Java Class.
  3. Name the class Car (capitalizing the first letter is a Java naming convention).
  4. Click Finish. This generates a new file named Car.java within your package.

Naming Convention for Classes:

  • Always start class names with a capital letter.
  • Use descriptive names that reflect the class’s purpose (e.g., Car, Person, Account).
  • This convention makes your code more readable and easier to understand.

Example 1:

class Car {
    String name;
    int maxSpeed;
    float price;
    int model;
}

Class Declaration:

  • class Car – This line declares a new class named Car.

Attributes:

  • String name; – This defines an attribute named name of type String. It will store the name of the car object.
  • int maxSpeed; – This defines an attribute named maxSpeed of type int. It will store the maximum speed of the car object in kilometers per hour.
  • float price; – This defines an attribute named price of type float. It will store the price of the car object in a floating-point format.
  • int model; – This defines an attribute named model of type int. It will store the model year of the car object.

Now we will create our instances for Car class in the Main class, because it is the entry point of the program where execution starts.

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.maxSpeed = 210;
        Car c2 = new Car();
        c2.name = "Kia";
        System.out.println(c1.name);
        System.out.println(c1.maxSpeed);
        System.out.println(c2.name);
    }
}

This code still uses the Car class with attributes like name, maxSpeed, price, and model.
Main Class:

  • public static void main(String args[]): This line remains the entry point of your program.
  • Car c1 = new Car();: This line creates a new instance of the Car class and assigns it to the variable c1.
  • c1.name = “Tesla”;: This line sets the name attribute of the c1 object to “Tesla”.
  • c1.maxSpeed = 210;: This line sets the maxSpeed attribute of the c1 object to 210 kilometers per hour.
  • Car c2 = new Car();: This line creates another new instance of the Car class and assigns it to the variable c2.
  • c2.name = “Kia”;: This line sets the name attribute of the c2 object to “Kia”.
  • System.out.println(c1.name);: This line prints the value of the name attribute of the c1 object to the console, which should output “Tesla”.
  • System.out.println(c1.maxSpeed);: This line prints the value of the maxSpeed attribute of the c1 object to the console, which should output “210”.
  • System.out.println(c2.name);: This line prints the value of the name attribute of the c2 object to the console, which should output “Kia”.

Example 2:

Car Class:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) {
        name = n;
    }
    String getName() {
        return name;
    }
}
  • It has four attributes: name, maxSpeed, price, and model. These attributes are not shown in this example, but they could store information about a car’s name, maximum speed, price, and model year.
  • It also has two methods:
    – setName(String n): This method takes a string argument n and sets the car’s name attribute to that value.
    – getName(): This method returns the current value of the car’s name attribute as a string.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setName("KIA");
        System.out.println(c1.getName());
    }
}
  • It creates a new instance of the Car class and assigns it to the variable c1.
  • It sets the car’s name attribute to “Tesla” using the direct assignment (c1.name = “Tesla”).
  • Then, it overwrites the name by calling the setName method with the argument “KIA”. This method changes the internal name attribute of the c1 object.
  • Finally, it prints the car’s name using the getName method, which retrieves the current value (“KIA”) and prints it to the console.

Example 3:

Class Car:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) { // Setters/ Mutators
        name = n;
    }
    String getName() {       // Getters/ Accessors
        return name;
    }
    void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    int getModel() {
        return model;
    }
}
  • Attributes: It still has name, maxSpeed, price, and model.
  • Methods:
    – Setters: These methods allow setting specific attribute values.
    – setName(String n): Sets the name attribute.
    – setModel(int m): Sets the model attribute with a validation check, only accepting years 2015 or later.
    – Getters: These methods retrieve specific attribute values.
    – getName(): Returns the name attribute value.
    – getModel(): Returns the model attribute value.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setModel(2021);
        System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object.
  • c1.name = “Tesla”;: Sets the name attribute of c1 using the default behavior (no setter needed).
  • c1.setModel(2021);: Sets the model attribute of c1 using the setter. Since 2021 is valid, it updates the model.
  • System.out.println(c1.getModel());: Prints the model attribute of c1, which should output “2021”.

Access Level Modifiers in Java

(Controlling Visibility and Encapsulation)

Access level modifiers are fundamental constructs in Java that determine the visibility and accessibility of class members (fields, methods, constructors). They play a crucial role in promoting encapsulation, a core principle of object-oriented programming that ensures data protection and modularity.

Key Concepts:

  • Visibility: Refers to whether a class member is directly visible and usable from other parts of your code.
  • Accessibility: Refers to the ability to directly access a class member without using special mechanisms.

Types of Access Level Modifiers:

  1. Public:
    Members declared public are visible and accessible from anywhere in your program.
    Use this modifier judiciously for elements that need to be widely used, but be cautious not to expose implementation details unnecessarily.
  2. Private:
    Members declared private are only visible and accessible within the class where they are defined.
    This promotes encapsulation by restricting direct access to internal data, encouraging the use of public methods to control interactions with the class.
  3. Protected:
    Members declared protected are visible and accessible within the class where they are defined, its subclasses in the same package, and subclasses in different packages (but not directly from other classes in different packages).
    This modifier is useful for creating a base class (superclass) with protected members that can be accessed and potentially overridden by its subclasses, promoting code reuse and inheritance.
  4. Default (Package-Private):
    Members declared without any access modifier are visible and accessible within the same package (the package containing the class definition).
    This provides a balance between visibility and access control within a package.

Example 4:

This code effectively demonstrates fundamental object-oriented concepts like encapsulation, access modifiers, and object interaction in Java. It provides a solid foundation for building more complex and robust Java applications.

Car Class:

public class Car { 
    private String name; 
    private int maxSpeed; 
    private float price; 
    private int model;
    
    public void setName(String n) { // Setters/ Mutators
        name = n;
    }
    public String getName() {       // Getters/ Accessors
        return name;
    }
    public void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    public int getModel() {
        return model;
    }
}
  • Attributes:
    – name: Private String storing the car’s name.
    – maxSpeed: Private int storing the car’s maximum speed.
    – price: Private float storing the car’s price.
    – model: Private int storing the car’s model year.
  • Methods:
    – setName(String n): Public setter to set the car’s name.
    – getName(): Public getter to retrieve the car’s name.
    – setModel(int m): Public setter to set the car’s model year, including validation for years 2015 or later.
    – getModel(): Public getter to retrieve the car’s model year.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
    c1.setModel(2021);
    System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object named c1.
  • c1.setModel(2021);: Attempts to set the model of c1 to 2021. This succeeds because 2021 is a valid year.
  • System.out.println(c1.getModel());: Prints the model of c1 to the console, which outputs “2021”.

Key Points:

  • Encapsulation: The Car class encapsulates its data using private attributes, ensuring controlled access through public methods.
  • Data Validation: The setModel method includes validation to prevent invalid model years, promoting data integrity.
  • Object Interaction: The Main class demonstrates how to create a Car object and interact with it using its public methods.
  • Setters and Getters: These methods provide a controlled way to modify and retrieve object attributes, upholding encapsulation principles.

Data Hiding

Data Hiding is a software development technique specifically used in object-oriented programming (OOP). Data hiding ensures exclusive data access to class members and protects object integrity by preventing unintended or intended changes.

Why do we use this technique?
Because we could have many object that will connect through messages and use each other methods.

Encapsulation
Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.

To achieve encapsulation in Java:

  • Declare the variables of a class as private.
  • Provide public setter and getter methods to modify and view the variables values.

Constructor (No-Arg, Parameterized, Default)

What is a Constructor?

  • It’s a special method in a Java class that’s automatically invoked when a new object of that class is created.
  • Its primary purpose is to initialize the object’s attributes (fields or variables) to appropriate initial values.
  • It ensures objects are created in a valid and consistent state.

Rules for Creating Constructors:

  1. Same Name as Class: The constructor’s name must be exactly the same as the class name.
  2. No Explicit Return Type: Constructors don’t have a return type, not even void.
  3. Cannot Have Modifiers: Constructors cannot be declared as abstract, static, final, or synchronized.

Constructor Types:

  1. No-Arg Constructor: a constructor that does not accept any arguments.
    public class Product {
        private String name;
        private String description;
        private float price;
        private int quantity;
        private float discount;
    
        public Product() {
            this.name = "No name";
            this.description = "No description";
            this.price = 0.0f;
            this.quantity = 0;
            this.discount = 0;
        }
    }
  2. Parameterized Constructor: a constructor that accepts arguments.
    public Product(String n, String d, float p, int q, float dis) {
            this.name = n;
            this.description = d;
            this.price = p;
            this.quantity = q;
            this.discount = dis;
        }
  3. Default Constructor: A constructor that is automatically created by Java compiler if it is not explicitly defined.

Constructor Chaining

Constructor Chaining: When a constructor calls another constructor of the same class then it is called constructor chaining.

Code:

Product class:

public class Product {
    private String name;
    private String description;
    private float price;
    private int quantity;
    private float discount;
    private String color;
    
    public Product() {
        this.name = "No name";
        this.description = "No description";
        this.price = 0.0f;
        this.quantity = 0;
        this.discount = 0;
    }
    
    public Product(String n, String d, float p, int q, float dis) {
        this.name = n;
        this.description = d;
        this.price = p;
        this.quantity = q;
        this.discount = dis;
        System.out.println("constructor: 5");
    }
    
    public Product(String n, String d, float p, int q, float dis, String c) {
        this (n,d,p,q,dis);
        this.color = c;
        System.out.println("constructor: 6");
    }
    
    public void display() {
        System.out.println("Name = " + name);
        System.out.println("description = " + description);
        System.out.println("Price = " + price);
        System.out.println("Quantity = " + quantity);
        System.out.println("Discount = " + Discount);
    }
}

Attributes:

  • name: String representing the product name.
  • description: String describing the product.
  • price: float storing the product price.
  • quantity: int representing the product quantity.
  • discount: float representing the discount percentage.
  • color: String (optional) for the product color (added in the third constructor).

Constructors:

  • Product() (Default Constructor): Initializes all attributes with default values (“No name”, “No description”, etc.).
  • Product(String n, String d, float p, int q, float dis): Parameterized constructor taking arguments for name, description, price, quantity, and discount. Prints “constructor: 5” upon invocation.
  • Product(String n, String d, float p, int q, float dis, String c): Parameterized constructor taking arguments for all attributes, including color. Internally calls the second constructor (“constructor: 5”) and then sets the color. Prints “constructor: 6” upon invocation.
  • display() method: Prints the product information in a user-friendly format.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Product p1 = new Product("Camera", "Auto focus", 99, 10, 5, "red");
        Product p2 = new Product();
        p.display();

    }
}

Creates two Product objects:

  • p1 using the third constructor, providing values for all attributes.
  • p2 using the default constructor (no arguments provided).

Attempts to call the display() method on the incorrectly referenced variable p (should be p2) to display the default values.

if

The if statement is a conditional statement in C++ that allows you to execute code based on a condition. The general syntax of an if statement is as follows:

if (condition) {
  // code to execute if the condition is true
}

The condition can be any Boolean expression. If the condition evaluates to true, the code block inside the if statement is executed. If the condition evaluates to false, the code block inside the else statement is executed.

Here is an example of an if statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is Positive" << endl;

    return 0;
}

Output:

  • Case 1: if you entered a positive digit like 5, your if condition will be true and the block of code that follows the condition will be executed.
    This number is Positive
  • Case 2: if you entered zero or a negative digit like -5, your if condition will be false and the block of code that follows the condition will not be executed which means that nothing will appear on your result screen.

C++

Welcome to the World of C++ Programming!

Hello, I’m Adel Nasim, the creator of Adel Nasim YouTube Channel, and I’m excited to guide you through the essentials of C++ programming. Whether you’re a novice or looking to deepen your skills, this written course, alongside my YouTube tutorials, is your comprehensive resource for mastering C++. We’ll cover everything from the basics to advanced concepts, ensuring you gain both theoretical knowledge and practical coding skills.

Get ready for a journey that blends theory with hands-on examples, equipping you with the confidence to tackle real-world challenges. Whether you’re building your programming foundation or enhancing existing skills, let’s dive into the world of C++ together. Happy coding!

Introduction

C++ is a cross-platform programming language that can be used to create high-performance applications. It is a general-purpose language, which means it can be used to develop a wide variety of software, including operating systems, games, embedded systems, and more.

C++ is a popular choice for developing high-performance applications because it gives programmers a high level of control over system resources and memory. It is also a very efficient language, which means that C++ programs typically run faster than programs written in other languages.

C++ is a relatively complex language to learn, but it is also a very powerful language. Once you have mastered the basics of C++, you will be able to develop almost any type of software you can imagine.

Why is C++?

C++ is one of the most popular programming languages in the world for a reason. It is a powerful, versatile, and efficient language that can be used to create a wide variety of software.

Here are just a few of the reasons why C++ is so popular:

  • Performance: C++ programs are typically very fast and efficient. This is because C++ gives programmers a high level of control over system resources and memory.
  • Versatility: C++ can be used to develop a wide variety of software, from operating systems to games to embedded systems.
  • Portability: C++ programs can be compiled and run on a variety of platforms, including Windows, macOS, Linux, and more.
  • Community: C++ has a large and active community of developers. This means that there is a wealth of resources available to help you learn and use C++.

Difference between C and C++

C++ was developed as an extension of the C programming language. Both languages have a similar syntax, but C++ adds a number of new features, including:

  • Classes and objects: C++ supports classes and objects, which provide a way to encapsulate data and code into reusable units.
  • Templates: C++ templates allow you to create generic functions and classes that can be used with different data types.
  • Exception handling: C++ provides exception handling features that allow you to deal with errors in a structured way.

Get Started

If you are interested in learning C++, there are a number of resources available to help you get started. There are many good books and tutorials available online, and there are also a number of C++ communities where you can ask for help and advice.

Once you have learned the basics of C++, you can start developing your own applications. There are a number of different C++ compilers and development environments available, so you can choose the one that best suits your needs.

Conclusion

C++ is a powerful and versatile programming language that can be used to create a wide variety of software. It is a popular choice for developing high-performance applications, and it is also a good choice for beginners because it is relatively easy to learn.

Getting Started

What is C++?

C++ is a general-purpose programming language that is used to create a wide range of applications, including operating systems, games, embedded systems, and web applications. C++ is known for its speed, efficiency, and flexibility.

Getting started with C++

To get started with C++, you will need to install a C++ compiler and IDE. A compiler is a program that converts C++ code into machine code that can be executed by a computer. An IDE is an integrated development environment that provides a variety of tools for writing, editing, compiling, and debugging C++ code.

Installing a C++ compiler and IDE

There are many different C++ compilers and IDEs available. For this tutorial, we will use Visual Studio for C++. Visual Studio is a free and powerful IDE that provides comprehensive support for C++ development.

To install Visual Studio for C++, visit the Visual Studio website and download the latest version.

Writing your first C++ program

Once you have installed Visual Studio for C++, you can start writing your first C++ program. To do this, create a new project and select the “C++ Console App” template.

Once you have created a new project, you can start writing C++ code in the main source file. The main source file is typically named main.cpp.

Here is a simple example of a C++ program:

C++
#include <iostream>
int main() {
  std::cout << "Hello, world!" << std::endl;
  return 0;
}

This program prints the message “Hello, world!” to the console.

Once you have written your C++ program, you can compile and run it by pressing F5.

Learning more about C++

Now that you have written your first C++ program, you can start learning more about the language. There are many resources available online and in libraries.

Here are a few tips for learning C++:

  • Start with the basics. Learn about variables, data types, operators, functions, and control flow statements.
  • Find a good tutorial or book. There are many resources available that can teach you the basics of C++.
  • Practice regularly. The best way to learn C++ is by writing code. Try to write simple programs at first, and gradually work your way up to more complex programs.
  • Use an IDE. An IDE can make it easier to write, edit, compile, and debug C++ code.

Conclusion

Getting started with C++ can be daunting, but it is also rewarding. C++ is a powerful and versatile language that can be used to create a wide range of applications.

By following the tips in this guide, you can start learning C++ today and start creating your own applications.

First Project in C++

 

Example:

C++

#include <iostream>
int main()
{ 
    std::cout << "Welcome to C++";
    return 0;
}


This is a simple C++ program that prints the message “Welcome to C++” to the console.

  • #include <iostream>: This line tells the compiler to include the header file iostream. This header file contains declarations for the standard input/output library.
  • int main(): This line defines the main function. The main function is the entry point for all C++ programs.
  • std::cout << “Welcome to C++”;: This line prints the message “Welcome to C++” to the console using the std::cout object.
  • return 0;: This line returns the value 0 from the main function. This indicates that the program terminated successfully.

When you compile and run this program, the following output will be printed to the console:

Welcome to C++

This is a very simple example of a C++ program, but it illustrates some of the basic concepts of the language, such as header files, functions, and input/output.

Escape Sequence

Escape sequences are special characters that are used to represent non-printing characters or to control the behavior of output streams. They are prefixed with a backslash (\).

Types of Escape Sequences

There are three types of escape sequences in C++:

  • Character escape sequences: These escape sequences represent non-printing characters, such as newline, tab, and backspace.
  • Hexadecimal escape sequences: These escape sequences represent characters using their hexadecimal values.
  • Octal escape sequences: These escape sequences represent characters using their octal values.

Common Escape Sequences

Here are some of the most common escape sequences in C++:

Escape Sequence Description
\n Newline
\t Tab
\\ Backslash
\" Double quote
\' Single quote
\? Question mark
\a Alert
\b Backspace
\f Form feed
\r Carriage return
\v Vertical tab
\x Hexadecimal escape sequence
\NNN Octal escape sequence

Using Escape Sequences

Escape sequences can be used in string and character literals. For example, the following code prints the string “Hello, world!” followed by a newline character:

C++
std::cout << "Hello, world!" << std::endl;

The std::endl object represents the newline character. It is equivalent to the escape sequence \n.

Escape sequences can also be used to represent non-printing characters, such as the tab character. For example, the following code prints the string “Hello, world!” followed by a tab character:

C++
std::cout << "Hello, world!" << '\t';

Example

Here are some more examples of how to use escape sequences in C++:

C++
// Print the string "This is a quote \" inside a string." 
std::cout << "This is a quote \" inside a string."; 

// Print the character 'a' with a backspace before it. 
std::cout << '\b' << 'a';

// Print the string "Hello, world!" followed by a newline character and a tab character. 
std::cout << "Hello, world!" << std::endl << '\t';
Conclusion

Escape sequences are a powerful tool that can be used to control the behavior of output streams and to represent non-printing characters in C++.

Variables vs Data type

Variables vs Data types in C++

Variables

Variables are named memory locations that can store data. They are declared using the var_name : data_type syntax. For example, the following code declares a variable named my_integer that can store an integer value:

C++
int my_integer;

Once a variable is declared, it can be used to store and retrieve data. For example, the following code assigns the value 10 to the my_integer variable:

C++
my_integer = 10;

The following code prints the value of the my_integer variable to the console:

C++
std::cout << my_integer << std::endl;

Output:

10

Data types

Data types define the type of data that a variable can store. C++ has a variety of data types, including integers, floating-point numbers, characters, strings, and Boolean values.

Here are some examples of data types in C++:

  • int: Stores integer values
  • float: Stores floating-point numbers
  • char: Stores a single character
  • string: Stores a sequence of characters
  • bool: Stores a Boolean value (true or false)

When a variable is declared, it must be assigned a data type. This tells the compiler how much memory to allocate for the variable and what type of data it can store.

For example, the following code declares a variable named my_string that can store a string value:

C++
string my_string;

The string data type is a special data type that is used to store sequences of characters.

Example

Here is an example of how to use variables and data types in C++:

C++
int my_integer = 10;
float my_floating_point_number = 3.14159;
char my_character = 'a';
string my_string = "Hello, world!";
bool my_boolean_value = true;

// Print the values of the variables.
std::cout << my_integer << std::endl;
std::cout << my_floating_point_number << std::endl;
std::cout << my_character << std::endl;
std::cout << my_string << std::endl;
std::cout << my_boolean_value << std::endl;

Output:

10
3.14159
a
Hello, world!
true

Variables and data types are essential concepts in C++. By understanding how they work, you can write more efficient and effective code.

Priorities & Calculations in C++

C++ has a set of operator precedence rules that determine the order in which expressions are evaluated. Operators with higher precedence are evaluated before operators with lower precedence.

Here is a table of the operator precedence rules in C++:

Operator Group Operators
Parentheses ()[]{}
Unary operators +-!~*&++--sizeofcasttype-name
Multiplication, division, and modulus */%
Addition and subtraction +-
Bitwise AND &
Bitwise OR |
Bitwise XOR ^
Equality and inequality ==!=
Less than, less than or equal to, greater than, greater than or equal to <<=>>=
Logical AND &&
Logical OR ||
Assignment =+=-=*=/=%=&=, `
Conditional operator ? :
Comma ,

When evaluating an expression, operators with the highest precedence are evaluated first, followed by operators with lower precedence.

Here are some examples of how operator precedence works in C++:

// Evaluates to 13.
int x = 5 * 2 + 3;

// Evaluates to 11.
int y = 5 + 2 * 3;

// Evaluates to true.
bool z = 5 < 10 && 10 > 5;

// Evaluates to false.
bool w = 5 > 10 || 10 < 5;

It is important to be aware of operator precedence when writing C++ code. Otherwise, you may get unexpected results.

Here is another example of how operator precedence can be used to control the order of evaluation:

// Evaluates to 16.
int a = (5 + 3) * 2;

// Evaluates to 11.
int b = 5 + (3 * 2);

In the first expression, the addition operator (+) has higher precedence than the multiplication operator (*). Therefore, the addition operation is evaluated first, and then the multiplication operation is evaluated.

In the second expression, the multiplication operation has higher precedence than the addition operation. Therefore, the multiplication operation is evaluated first, and then the addition operation is evaluated.

By understanding operator precedence, you can write more concise and efficient C++ code.

Basic Arithmetic & Casting

Basic Arithmetic in C++

C++ provides a number of operators for performing basic arithmetic operations. These operators include:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulo (remainder)

These operators can be used to perform arithmetic operations on variables of different data types. For example, the following code performs arithmetic operations on variables of type int and float:

int a = 10;
float b = 3.14159;

// Add two integers.
int c = a + 5;

// Multiply two floats.
float d = b * 2;

// Divide two integers.
float e = a / 2;

// Calculate the remainder of a division operation.
int f = a % 2;

The results of these operations are stored in the corresponding variables.

Casting in C++

Casting is a way to convert a value from one data type to another. This can be useful when you need to perform arithmetic operations on values of different data types.

There are two types of casting in C++:

  • Implicit casting: Implicit casting occurs when the compiler automatically converts a value from one data type to another. For example, the following code implicitly converts the value of the variable a from type int to type float before performing the multiplication operation:

 

int a = 10;
float b = 3.14159;

// Multiply an int and a float.
float c = a * b;
  • Explicit casting: Explicit casting is when the programmer explicitly converts a value from one data type to another. This can be done using the cast operators (static_castreinterpret_castconst_cast, and dynamic_cast). For example, the following code explicitly converts the value of the variable b from type float to type int before performing the division operation:

 

int a = 10;
float b = 3.14159;

// Divide a float by an int.
int c = static_cast<int>(b) / a;

Explicit casting is often used to prevent errors that can occur when implicitly casting values.

Example

Here is an example of how to use casting in C++:

// Convert a string to an integer.
int a = static_cast<int>("10");

// Convert a floating-point number to a character.
char b = static_cast<char>(3.14159);

// Convert a pointer to an integer to a pointer to a float.
float *c = reinterpret_cast<float*>(pInt);

// Convert a const object to a non-const object.
int *d = const_cast<int*>(pInt);

Casting can be a powerful tool for converting values between different data types. However, it is important to use it carefully to avoid errors.

Prefix and Postfix & Compound assignment

Prefix and postfix operators in C++

Prefix and postfix operators are used to modify the value of a variable. The prefix operator is used before the variable, while the postfix operator is used after the variable.

The following table shows some of the most common prefix and postfix operators in C++:

Operator Prefix Postfix
++ Increments the value of the variable by 1. Increments the value of the variable by 1, and returns the original value.
Decrements the value of the variable by 1. Decrements the value of the variable by 1, and returns the original value.

Example

The following code shows how to use the prefix and postfix operators to increment the value of a variable:

int a = 10;

// Increment the value of a by 1 using the prefix operator.
a++;

// Increment the value of a by 1 using the postfix operator.
int b = a++

// Print the values of a and b.
std::cout << a << " " << b << std::endl;

Output:

12 11

Compound assignment operators in C++

Compound assignment operators combine arithmetic operations with assignment operations. This makes it possible to modify the value of a variable in a single statement.

The following table shows some of the most common compound assignment operators in C++:

Operator Description Example
+= Adds the operand to the left operand x += 5; is equivalent to x = x + 5;
-= Subtracts the operand from the left operand y -= 3; is equivalent to y = y - 3;
*= Multiplies the operand with the left operand z *= 2; is equivalent to z = z * 2;
/= Divides the left operand by the operand a /= 4; is equivalent to a = a / 4;
%= Computes the modulo of the left operand and the operand b %= 7; is equivalent to b = b % 7;
&= Performs a bitwise AND operation on the left operand and the operand c &= 6; is equivalent to c = c & 6;
^= Performs a bitwise XOR operation on the left operand and the operand e ^= 8; is equivalent to e = e ^ 8;
<<= Shifts the left operand left by the number of bits specified by the operand f <<= 3; is equivalent to f = f << 3;
>>= Shifts the left operand right by the number of bits specified by the operand g >>= 2; is equivalent to g = g >> 2;

Example

The following code shows how to use compound assignment operators to modify the value of a variable:

int a = 10;

// Increment the value of a by 1 using the compound assignment operator.
a += 1;

// Print the value of a.
std::cout << a << std::endl;

Output:

11

Compound assignment operators can be a powerful tool for writing concise and efficient C++ code.

Variable Scope (Local vs Global)

Variable scope is a concept in programming that determines where a variable can be accessed from in a program. There are two types of variable scope in C++: local and global.

  • Local variables: Local variables are declared within a function or block of code. They can only be accessed from within the function or block of code in which they are declared.
  • Global variables: Global variables are declared outside of any function or block of code. They can be accessed from anywhere in the program.

Example of local variable scope:

int main() {
  int local_variable = 10;

  // local_variable can only be accessed from within this function.
  std::cout << local_variable << std::endl;

  // This code will cause an error because local_variable is not accessible here.
  std::cout << global_variable << std::endl;

  return 0;
}

Example of global variable scope:

int global_variable = 20;

int main() {
  // global_variable can be accessed from anywhere in the program.
  std::cout << global_variable << std::endl;

  // This code is also valid.
  int local_variable = global_variable;

  return 0;
}

It is important to be aware of variable scope when writing C++ code. Otherwise, you may accidentally access a variable that is not defined or that you are not supposed to access.

Here are some general rules for variable scope in C++:

  • Local variables are scoped to the function or block of code in which they are declared.
  • Global variables are scoped to the entire program.
  • Variables declared in a function can shadow variables declared in the global scope.
  • Variables declared in a block of code can shadow variables declared in the function scope.

By understanding variable scope, you can write more efficient and reliable C++ code.

Selection Statement - if Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

In this section will know more about if statement.

if

The if statement is a conditional statement in C++ that allows you to execute code based on a condition. The general syntax of an if statement is as follows:

if (condition) {
  // code to execute if the condition is true
}

The condition can be any Boolean expression. If the condition evaluates to true, the code block inside the if statement is executed. If the condition evaluates to false, the code block inside the else statement is executed.

Here is an example of an if statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is Positive" << endl;

    return 0;
}

Output:

  • Case 1: if you entered a positive digit like 5, your if condition will be true and the block of code that follows the condition will be executed.
    This number is Positive
  • Case 2: if you entered zero or a negative digit like -5, your if condition will be false and the block of code that follows the condition will not be executed which means that nothing will appear on your result screen.

else

The else statement in C++ is used to provide an alternate block of code to be executed if the condition of an if statement is false.

The general syntax of an else statement is as follows:

if (condition) {
  // code to execute if the condition is true
} else {
  // code to execute if the condition is false
}

For example, the following code uses an else statement to print a different message depending on whether the number variable is positive or negative:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is positive" << endl;
    else
        cout << "This number is negative" << endl;


    return 0;
}

Output should be one of the previous statements depending on the entered number. if the number is positive like 5, the output will be “This number is positive” and vice versa.

The else statement is a powerful tool for controlling the flow of your program. By using else statements, you can write more complex and efficient code.

Here are some general rules for using the if else statement:

  • The else statement must be used in conjunction with an if statement.
  • The else statement can be used to provide an alternate block of code to be executed if the condition of the if statement is false.
  • You can use nested if else statements to create more complex conditional statements:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int x = 0;
        cin >> x;
        if (x % 2 == 0)
            if (x > 50)
                cout << "it's Ok" << endl;
            else
                cout << "it's not Ok" << endl;
        else
            cout << "Odd" << endl;
    
    
        return 0;
    }
    

By understanding how to use the if else statement, you can write more efficient and reliable C++ code.

else if

Logical Operators

Logical operators in C++ are used to combine or modify Boolean expressions. They allow you to create more complex conditional statements.

The three logical operators in C++ are:

  • And (&&): Returns true if both of its operands are true. Otherwise, it returns false.
  • Or (||): Returns true if either of its operands is true. Otherwise, it returns false.
  • Not (!): Negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.

Logical operators can be used to create more complex conditional statements. For example, the following code uses the && operator to check if a digit is in a specific range of numbers or not:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cout << "Enter a number";
    cin >> x;
    if (x >= 1 && x <= 100)
        cout << "Ok" << endl;
    else
        cout << "Out of range" << endl;

    return 0;
}

Another Example:

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    cout << "Enter your age";
    cin >> a;
    char g = '\0';
    cout << "Enter your gender";
    cin >> g;
    
    if (a < 18 && g == 'm')
        cout << "male, " << "young boy" << endl;
    else if (a >= 18 && g == 'm')
        cout << "male," << "grown up man" << endl;
    else if (a < 18 && g == 'f')
        cout << "female," << "young girl" << endl;
    else
        cout << "female," << "grown up girl" << endl;
    
    return 0;
}

Note : \0 in C++ is a null character. It is a character with all bits set to zero. It is used to mark the end of a string in C++.

The following code uses the || operator to check if a number is greater than 10 or less than 5:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (number > 10 || number < 5) 
        cout << "The number is greater than 10 or less than 5." << endl;
    
    return 0;
}

The following code uses the ! operator to negate the value of the Boolean expression number > 10:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (! (number > 10)) 
        cout << "The number is not greater than 10." << endl;
    
    return 0;
}

Logical operators can be used to create very complex conditional statements. However, it is important to use them carefully to avoid making your code difficult to read and maintain.

Here are some general rules for using logical operators:

  • Logical operators can be used to combine Boolean expressions to create more complex conditional statements.
  • The && operator returns true if both of its operands are true. Otherwise, it returns false.
  • The || operator returns true if either of its operands is true. Otherwise, it returns false.
  • The ! operator negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.
  • Logical operators can be used in nested expressions.

By understanding how to use logical operators, you can write more efficient and reliable C++ code.

Selection Statement – Switch Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

We explained “if statement” in “Selection Statement – if Statement” section, and now we are going to explain more about “switch statement”.

The switch statement in C++ is a control statement that allows you to execute different blocks of code based on the value of an expression. The general syntax of a switch statement is as follows:

switch (expression) {
  case value1:
    // code to execute if expression equals value1
  case value2:
    // code to execute if expression equals value2
  ...
  default:
    // code to execute if expression does not equal any of the values in the case statements
}

The expression can be any integer expression. The switch statement evaluates the expression and compares it to the values of the case statements. If the expression equals one of the values in the case statements, the code block inside that case statement is executed. If the expression does not equal any of the values in the case statements, the code block inside the default statement is executed.

Here is an example of a switch statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    
    switch (x)
    {
        case 1: cout << "case #1" << endl;
            break;
        case 2: cout << "case #2" << endl;
            break;
        case 3: cout << "case #3" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

You can also use characters instead of numbers in switch statement. For Example:

#include <iostream>

using namespace std;

int main()
{
    char c = 'a';
    
    switch (c)
    {
        case 'a': cout << "case #a" << endl;
            break;
        case 'b': cout << "case #b" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

Output will be:

case #a

Remember!
Using a capital letter like ‘A’ in the previous example is not like using a small letter like ‘a’. They are not the same!

Benefits of using switch statements

Switch statements can be more efficient than using a series of if statements, especially when there are many different cases. Switch statements can also make your code more readable and maintainable.

Conclusion

Switch statements are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Repetition Statement

A repetition statement in C++ is a control statement that allows you to execute a block of code repeatedly until a certain condition is met. There are three types of repetition statements in C++:

  • while loop: The while loop executes a block of code repeatedly while a condition is true.
  • do-while loop: The do-while loop executes a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again.
  • for loop: The for loop executes a block of code a fixed number of times.

Repetition statements are a powerful tool for controlling the flow of your C++ program. They can be used to solve a variety of problems, such as:

  • Iterating over a collection of data
  • Performing a task a certain number of times
  • Waiting for a certain event to occur

While Loop

The while loop in C++ is a control statement that allows you to execute a block of code repeatedly while a condition is true. The general syntax of a while loop is as follows:

while (condition) {
  // code to execute while the condition is true
}

The condition can be any Boolean expression. The while loop evaluates the condition and if it is true, the code block inside the while loop is executed. The code block inside the while loop is executed repeatedly until the condition evaluates to false.

Here is an example of a while loop:

#include <iostream>

using namespace std;

int main()
{
    while (true)
    {
        cout << " a word" <<endl;
    }
    
    return 0;
}

The previous code is a simple infinite loop in C++. It will print the phrase “a word” to the console forever, or until the program is terminated.

The while (true) statement creates an infinite loop. This means that the code block inside the loop will be executed forever, or until the program is terminated.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler evaluates the condition of the while statement. Since the condition is always true, the code block inside the loop is executed.
  2. The compiler prints the phrase “a word” to the console.
  3. The compiler goes back to step 1 and repeats the process.

This process continues forever, or until the program is terminated.

To terminate the program, you can press Ctrl+C on your keyboard.

Here are some things to keep in mind about infinite loops:

  • Infinite loops can be useful for certain tasks, such as polling for input or waiting for a certain event to occur.
  • However, it is important to use infinite loops carefully, as they can also cause your program to crash if you are not careful.
  • For example, if you accidentally create an infinite loop that prints output to the console, your console window will quickly fill up with output and your program will become unresponsive.

To overcome these problems we should make 3 steps:

  1. declare a variable and initializes it to any value we want.
  2. add a condition to while statement.
  3. set a counter for our variable.

These steps are shown in the following example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0;
    while (c < 5)
    {
        cout << " a word" <<endl;
        c++;
    }
    
    return 0;
}

int c = 0;, declares an integer variable named c and initializes it to the value 0.

The while (c < 5) statement creates a loop that will iterate as long as the value of the c variable is less than 5.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

The c++; statement increments the value of the c variable by 1.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the c variable and initializes it to the value 0.
  2. The compiler evaluates the condition of the while statement. Since the condition is true, the code block inside the loop is executed.
  3. The compiler prints the phrase “a word” to the console.
  4. The compiler increments the value of the c variable by 1.
  5. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 5. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

Here is the output of this program:

a word
a word
a word
a word
a word

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    while (c < 4)
    {
        cout << "Enter a number: ";
        cin >> num;
        sum = sum + num;
        c++;
    }
    cout << " sum = " << sum << endl;
    return 0;
}

This code is a simple C++ program that prompts the user to enter four numbers and then prints the sum of those numbers to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The while (c < 4) statement creates a loop that will iterate as long as the value of the c variable is less than 4.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum = sum + num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 4. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

After the loop has terminated, the program prints the message ” sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
 sum = 100

While loops are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Here are some tips for using while loops:

  • Make sure that the condition of the while loop will eventually evaluate to false. Otherwise, the while loop will run forever.
  • Use a break statement to exit the while loop early.
  • Use a continue statement to skip the rest of the current iteration of the while loop.

Do - while loop

The do-while loop in C++ is a control statement that allows you to execute a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

The general syntax of a do-while loop is as follows:

do {
  // code to execute
} while (condition);

The condition can be any Boolean expression. The do-while loop executes the code block at least once, and then it evaluates the condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

Here is an example of a do-while loop:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    do
    {
        cout << "Enter a number: ";
        cin >> num;
        sum += num;
        c++;
    }
    while (c <= 4);
    cout << "sum = " << sum << endl;
    return 0;
}

This code prompts the user to enter four numbers and then prints the sum of those numbers to the console. The program uses a do-while loop to ensure that the user enters at least one number, even if they enter an invalid number the first time.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The do statement begins the do-while loop.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum += num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The while (c <= 4); statement evaluates the condition of the do-while loop. If the c variable is less than or equal to 4, the loop will continue to iterate. Otherwise, the loop will terminate.
  8. If the condition of the loop is true, the code block inside the loop is executed.
  9. Steps 3-7 are repeated until the condition of the loop is false.
  10. After the loop has terminated, the program prints the message “sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
sum = 100

Do-while loops can be used to solve a variety of problems, such as:

  • Validating user input
  • Checking for a certain condition to be met
  • Performing a task a certain number of times

The differences between while loop and do – while loop:

Feature While loop Do-while loop
Condition is checked Before the code block is executed. After the code block is executed.
Guarantee of execution The code block is not guaranteed to be executed at least once. The code block is guaranteed to be executed at least once.

Table explanation

  • While loop: The while loop checks the condition before the code block is executed. If the condition is true, the code block is executed. The code block is executed repeatedly until the condition evaluates to false.
  • Do-while loop: The do-while loop checks the condition after the code block is executed. The code block is executed at least once, regardless of the value of the condition. The code block is executed repeatedly until the condition evaluates to false.

For loop

The for loop in C++ is a control statement that allows you to execute a block of code repeatedly a certain number of times. The general syntax of a for loop is as follows:

for (initialization; condition; increment) {
  // code to execute
}

The initialization statement is executed once, before the for loop starts. The condition statement is evaluated before each iteration of the loop. If the condition is true, the code block inside the loop is executed. The increment statement is executed after each iteration of the loop.

Here is an example of a for loop:

#include <iostream>

using namespace std;

int main()
{
    
    for (int c = 0; c < 10; c++)
    {
        cout << c << endl;
    }
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the c variable to 0.
  2. The condition statement checks if the c variable is less than 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the c variable to the console.
  4. The increment statement increments the c variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

0
1
2
3
4
5
6
7
8
9

Here is another example that prompts the user to enter 10 marks and then prints the average of those marks to the console:

#include <iostream>

using namespace std;

int main()
{
    int m = 0, sum = 0;
    for (int i = 1; i <= 10; i++)
    {
        cout << "Enter your marks:";
        cin >> m;
        sum = sum + m;
    }
    cout << "the avg = " << ((double)sum / 10) << endl;
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 1.
  2. The condition statement checks if the i variable is less than or equal to 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prompts the user to enter their marks and stores the value in the m variable. The code block also adds the value of the m variable to the sum variable.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

After the for loop has terminated, the program prints the average of the marks to the console. The average is calculated by dividing the sum of the marks by the number of marks.

You used the (double) cast in the expression ((double)sum / 10) to ensure that the result of the division operation is a floating-point number. This is important because the sum variable is an integer variable, and the division of two integers results in an integer. If you did not use the (double) cast, the program would print the integer result of the division operation to the console, which may not be accurate.

Here is an example of the output of this program:

Enter your marks: 10
Enter your marks: 20
Enter your marks: 30
Enter your marks: 40
Enter your marks: 50
Enter your marks: 60
Enter your marks: 70
Enter your marks: 80
Enter your marks: 90
Enter your marks: 100
the avg = 55.000000

This code prints the numbers from 10 to 50 to the console, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i <= 50; i++)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is less than or equal to 50. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Why is size_t used as the loop counter?

The size_t type is used as the loop counter because it is the type that is returned by the sizeof operator. This ensures that the loop counter can be used to iterate over any type of data, including arrays and objects.

This code prints the numbers from 10 to 1 to the console, in reverse order, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i >= 1; i--)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is greater than or equal to 1. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The decrement statement decrements the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 9 8 7 6 5 4 3 2 1

Examples of loop break vs continue

break and continue are two flow control statements in C++ that can be used to alter the normal flow of a loop.

break terminates the loop immediately and unconditionally.

continue skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is an example of how to use continue in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 5)
            continue;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 9, inclusive, except for the number 5. The if statement inside the loop checks if i is equal to 5. If it is, the continue statement skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 5.
  4. If i is equal to 5, the program skips the rest of the current iteration of the loop using the continue statement.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times.

Here is the output of this code:

i = 0
i = 1
i = 2
i = 3
i = 4
i = 6
i = 7
i = 8
i = 9

Here is an example of how to use break in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 4)
            break;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 3, inclusive. The if statement inside the loop checks if i is equal to 4. If it is, the break statement terminates the loop immediately and unconditionally.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 4.
  4. If i is equal to 4, the break statement terminates the loop immediately and unconditionally.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times or until the loop is terminated by the break statement.

In this case, the loop will be terminated by the break statement when i is equal to 4. Therefore, the output of the code will be:

i = 0
i = 1
i = 2
i = 3

Which one to use?

Which one to use depends on what you want to achieve. If you want to terminate the loop immediately, use break. If you want to skip the rest of the current iteration of the loop and continue with the next iteration, use continue.

Here are some general tips for using break and continue:

  • Use break sparingly. Terminating a loop early can make your code more difficult to read and understand.
  • Use continue to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using continue.
  • Use break and continue to make your code more efficient. For example, you can use break to terminate a loop early if you have already found what you are looking for.

Nested Loop

A nested loop is a loop that is contained within another loop. This means that the inner loop will iterate for each iteration of the outer loop.

Here is an example of a nested loop in C++:

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= 6; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

This code is a nested for loop that prints a rectangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates 6 times. This means that the code inside the inner loop will be executed 30 times.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 6. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 6.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

******
******
******
******
******

Nested loops can be used to solve a variety of problems. For example, you could use nested loops to iterate over all the elements of a two-dimensional array, or to generate all the possible combinations of two sets of values.

Here are some tips for using nested loops:

  • Use nested loops sparingly. Nested loops can make your code more difficult to read and understand.
  • Use nested loops to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using nested loops.
  • Use nested loops to make your code more efficient. For example, you can use nested loops to avoid searching for an element in an array multiple times.

Draw shapes (Triangle)

You can use the logic of nested loops to create different shapes, for example a triangle.

This code is a nested for loop that prints a triangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

*
**
***
****
*****

What if we want to draw this triangle upside down?

We change the condition in our outer for loop.

This code is a nested for loop that prints an inverted triangle of asterisks to the console. The outer loop iterates from 5 to 1, inclusive, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 5 and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is greater than or equal to 1. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then decrements i by 1.
  9. The outer for loop repeats steps 3-8 until i is less than 1.

Here is the output of the code:

*****
****
***
**
*

Can we make it harder?

This code prints a right triangle of asterisks to the console. The outer loop iterates from 1 to 5, inclusive, and the inner loop iterates from 4 to i, inclusive, where i is the current iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares three variables ij, and k, and initializes them to 1, 4, and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is greater than or equal to i. If it is, the program prints a space to the console.
  5. The inner for loop then decrements j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is less than i.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments i by 1.
  10. The outer for loop repeats steps 3-9 until i is greater than 5.

Here is the output of the code:

    *
   **
  ***
 ****
*****

Let’s print it upside down!

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Look what we have here as an output!

*****
 ****
  ***
   **
    *

Let’s draw a different triangle

#include <iostream>

using namespace std;

int main()
{
    int e = 1;
    for (int a = 1; a <= 5; a++)
    {
        for (int b = 4; b >= a; b--)
        {
            cout << " ";
        }
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e + 2;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares four variables ea, c, and b, and initializes them to 1, 1, 0 and 4, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if a is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if b is greater than or equal to a. If it is, the program prints a space to the console.
  5. The inner for loop then decrements b by 1.
  6. The inner for loop repeats steps 4 and 5 until b is less than a.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments a by 1.
  10. The outer for loop repeats steps 3-9 until a is greater than 5.

Here is the output of the code:

    *
   ***
  *****
 *******
*********

Let’s make it upside down:

#include <iostream>

using namespace std;

int main()
{
    int e = 9;
    for (int r = 1; r <= 5; r++)
    {
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e - 2;
        for (int s = 0; s < r; s++)
        {
            cout << " ";
        }
    }

    return 0;
}

Output:

*********
 *******
  *****
   ***
    *

You can also use nested loops to draw other shapes, such as squares, rectangles, and diamonds.

Draw shapes (square), Draw any Letter Ex:( X,Z,N,E,F)

Nested loops in C++ are a powerful tool for drawing different shapes to the console. By using nested loops, we can iterate over multiple dimensions and print different characters to create different patterns.

Example 1:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == 1 || i == 10)
                cout << "*";
            else if (j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

This code prints a hollow square of asterisks to the console. The outer for loop iterates from 1 to 10, inclusive, and the inner for loop iterates from 1 to 10, inclusive.

The if statement inside the inner for loop checks if i is equal to 1 or 10, or if j is equal to 1 or 10. If any of these conditions are met, the program prints an asterisk to the console. Otherwise, the program prints a space to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 10. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 10. If it is, the program prints an asterisk to the console if i is equal to 1 or 10, or if j is equal to 1 or 10. Otherwise, the program prints a space to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 10.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 10.

Here is the output of the code:

**********
*        *
*        *
*        *
*        *
*        *
*        *
*        *
*        *
**********

Example 2:

If we want to print a letter like X to the console, expecting an output like this:

*   *
 * * 
  *  
 * * 
*   *

We need to set our logic.
To understand how we can put the asterisks in the previous shape, let’s present them this way:

/*
 1 2 3 4 5
1* * * * *
2* * * * *
3* * * * *
4* * * * *
5* * * * *
*/

Now let’s think about it looking at this shape, when the column meets the row we get a star, so we need a loop that goes through all the meeting points between every row and column and we need an if condition to specify our exact locations to make two diagonal lines cross forming our X letter shape.

all of this is represented in the following code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (i == j || j == 6-i)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Example 3:

By understanding how we asterisks are lined here:

/*
 1 2 3 4 5 
1* * * * * 
2* * * * * 
3* * * * * 
4* * * * * 
5* * * * * 
*/

We can think of multiple ways to manipulate our code producing different letters and shapes..

Look at this code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (j == (6) - i || i == 1 || i == 5)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Guess what this shape is?!

Output:

*****
   *
  *  
 *   
*****

Example 4:

Now let’s make our shape more complicated

**********
**      **
* *    * *
*  *  *  *
*   **   *
*   **   *
*  *  *  *
* *    * *
**      **
**********

Applying this code which is no different than previous examples

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == j || j == 11 - i || i == 1 || i == 10 || j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

 

Function Part 1

A function in C++ is a block of code that performs a specific task. Functions can be used to encapsulate common operations, making your code more reusable and easier to understand. Functions can also be used to improve the performance of your code by avoiding duplicate code.

To create a function in C++, you use the following syntax:

return_type function_name(parameter_list) {
  // Function body
}

The return_type specifies the type of data that the function will return. The function_name is the name of the function. The parameter_list is a list of parameters that the function will accept. The function_body is the code that the function will execute.

Here is an example of a simple function in C++:

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}

This function takes two integer parameters, x and y, and returns the sum of those two parameters.

To call a function, you simply use its name followed by a pair of parentheses. For example, to call the sum() function, you would write:

int s = sum(10, 20);

This would assign the value 30 to the variable s.

The code could be written this way:

#include <iostream>

using namespace std;

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}
int main()
{
    int s = 0;
    s = sum(10, 20);
    cout << "sum = " << s << endl;
    
    return 0;
}

The following example takes two float parameters and return the sum of them:

#include <iostream>

using namespace std;

float sum(float x, float y)
{
    float s = 0;
    s = x + y;
    return s;
}
int main()
{
    float s = 0;
    s = sum(20.5, 30.6);
    cout << "sum = " << s << endl;
    
    return 0;
}

Output:

sum = 51.1

The importance of using return:

We need to write a return in a function in C++ to specify the value that the function will return to the calling function. This is important because it allows us to use the function to perform calculations and then use the result of those calculations in our code.

Without the return statement, the function would not be able to return any value to the calling function. This would mean that we would not be able to use the function to perform calculations and then use the result of those calculations in our code.

By using the return statement, we can terminate the execution of the function early and avoid the error. This makes our code more robust and reliable.

Overall, the return statement is an important part of C++ programming. It allows us to return values from functions and to terminate the execution of functions early. This makes our code more reusable, efficient, and reliable.

But can we write a function without using return?

See this example:

#include <iostream>

using namespace std;

void print()
{
    cout << "myName" << endl;
}

int main()
{
    print();
    
    return 0;
}

This code defines a function called print() and a main function. The print() function simply prints the string “myName” to the console. The main function calls the print() function and then returns 0.

The print() function is declared with the void return type. This means that the function does not return any value. We use the void return type when we want a function to perform an action but not return any value.

When you run this code, the following output will be printed to the console:

myName

We use the void return type for the print() function because we only want it to print the string “myName” to the console. We do not need the function to return any value.

 

Functions can also be nested, meaning that one function can call another function. This can be useful for breaking down complex tasks into smaller, more manageable functions.

Functions are a powerful tool in C++ and can be used to improve the quality and performance of your code.

Here are some tips for using functions in C++:

  • Give your functions meaningful names. This will make your code more readable and easier to maintain.
  • Use functions to encapsulate common operations. This will make your code more reusable and easier to understand.
  • Use functions to improve the performance of your code by avoiding duplicate code.
  • Use functions to break down complex tasks into smaller, more manageable functions.

Function Part 2

Example 1:

#include <iostream>

using namespace std;

double avg(int m1, int m2, int m3) 
{
    return double(m1 + m2 + m3) / 3;
}

int main()
{
    int mm1, mm2, mm3;
    cout << "Enter your marks" << endl;
    cin >> mm1 >> mm2 >> mm3;
    cout << "avg = " << avg(mm1, mm2, mm3) << endl;
    
    return 0;
}

This code defines a function called avg(), which takes three integer parameters (m1, m2, and m3) and returns the average of those three parameters as a double value.

The function works by first converting the integer parameters to double values using the double() function. This is necessary because the average of three integers is a fractional number, and we want the function to return a double value.

Next, the function calculates the sum of the three parameters and divides that sum by 3. This gives us the average of the three parameters.

Finally, the function returns the average value.

The program works as follows:

  1. The program declares three integer variables mm1mm2, and mm3 to store the marks entered by the user.
  2. The program prompts the user to enter their marks and reads the marks into the three variables.
  3. The program calls the avg() function to calculate the average of the three marks.
  4. The program prints the average to the console.

Example 2:

#include <iostream>

using namespace std;

int max(int n1, int n2, int n3) 
{
    int mx = n1;
    if (mx < n2)
        mx = n2;
    if (mx < n3)
        mx = n3;
    return mx;
}

int min(int n1, int n2, int n3) 
{
    int mn = n1;
    if (mn > n2)
        mn = n2;
    if (mn > n3)
        mn = n3;
    return mn;
}

int main()
{
    cout << "max = " << max(100, 200, 300) << endl;
    cout << "min = " << min(100, 200, 300) << endl;
    
    return 0;
}

This code defines two functions called max() and min()which both take three integer parameters (n1, n2, and n3) and returns the largest and the smallest of those three parameters.

The first function works by first initializing a variable called mx to the value of the first parameter, n1. Then, the function checks if mx is less than the second parameter, n2. If it is, the function assigns the value of n2 to mx. Next, the function checks if mx is less than the third parameter, n3. If it is, the function assigns the value of n3 to mx. Finally, the function returns the value of mx, which is the largest of the three parameters.

The second function works by first initializing a variable called mn to the value of the first parameter, n1. Then, the function checks if mn is greater than the second parameter, n2. If it is, the function assigns the value of n2 to mn. Next, the function checks if mn is greater than the third parameter, n3. If it is, the function assigns the value of n3 to mn. Finally, the function returns the value of mn, which is the smallest of the three parameters.

Here is the output of the program:

min = 100
max = 300

There are two ways to define a function in a C++ program:

  1. Function declaration: This is a prototype of the function that tells the compiler about the function’s name, return type, and parameters. The function declaration must be placed before the first call to the function.
  2. Function definition: This is the actual code that implements the function. The function definition can be placed anywhere in the program, but it is generally placed at the end of the program.

For example, here is a function declaration and definition:

// Function declaration
int add(int a, int b);

// Function definition
int add(int a, int b) {
  return a + b;
}

The function declaration tells the compiler that there is a function called add() that takes two integer parameters and returns an integer value. The function definition provides the actual code that implements the function.

You can also arrange function declarations and definitions in different ways in your code. For example, you can:

  • Declare all of your functions at the beginning of your program and then define them at the end of your program.
  • Declare and define your functions in the order that they are called in your program.
  • Declare your functions in a header file and define them in a source file.

The best arrangement for your code will depend on the specific needs of your program.

Here is an example of how to use function declarations and definitions in a C++ program:

// Function declaration
int add(int a, int b);

int main() {
  // Function call
  int sum = add(1, 2);

  // Print the sum
  cout << "The sum is: " << sum << endl;

  return 0;
}

// Function definition
int add(int a, int b) {
  return a + b;
}

Of course you should pay a massive attention to the sequential arrangement of your program.

The sequential arrangement of functions in a C++ program is important for two main reasons:

  • Readability: A well-organized program is easier to read and understand. By arranging functions in a logical order, you can make it easier for other programmers to follow the flow of your code.
  • Maintainability: A well-maintained program is easier to update and fix bugs in. By arranging functions in a logical order, you can make it easier to find and fix problems in your code.

Note !

The main function is the entry point for all C++ programs. It is the first function that is called when the program is executed. The main function is responsible for initializing the program, calling other functions, and returning a value to the operating system.

The main function is important for several reasons:

  • It is the starting point for the program execution.
  • It is responsible for initializing the program.
  • It controls the flow of the program by calling other functions.
  • It returns a value to the operating system when the program terminates.

Without the main function, the program would not be able to start executing.

Here is an example of a simple main function in C++:

int main() {
  // Initialize the program
  // ...

  // Call other functions
  // ...

  // Return a value to the operating system
  return 0;
}

This main function initializes the program, calls other functions, and returns a value of 0 to the operating system.

You can use the main function to control the flow of your program by calling other functions. For example, you could write a function to calculate the sum of two numbers and then call that function from the main function.

You can also use the main function to return a value to the operating system. This value is used to indicate whether the program terminated successfully or not.

The main function is a very important part of any C++ program. It is the starting point for the program execution, and it controls the flow of the program.

Example 3:

#include <iostream>

using namespace std;

int avg(int x, int y, int z)
{
    return (x + y + z) / 3;
}

void print()
{
    cout << "Hello" << endl;
}

void xy()
{
    cout << 5 * 10 << endl;
}

int main()
{
    cout << "Nothing" << endl;
    return 0;
}

int f2()
{
    return 5;
}

This code defines four functions: avg(), print(), xy(), and f2(). The avg() function takes three integer parameters and returns the average of those three parameters. The print() function prints the string “Hello” to the console. The xy() function prints the product of 5 and 10 to the console. The f2() function returns the integer 5.

The main function in the code simply prints the string “Nothing” to the console and then returns 0.

When you run this code, the following output will be printed to the console:

Nothing

This is because the only function that is called from the main function is the cout << "Nothing" << endl; statement.

You can use the other functions in the code by calling them from the main function or from other functions.

Function part 3 (built in functions)

Built-in functions in C++ are functions that are provided by the compiler and are available to use in any C++ program. These functions are typically used for common tasks such as input/output, mathematical operations, and string manipulation.

Here are some of the most common built-in functions in C++:

  • Mathematical functions:
    • abs(): Returns the absolute value of a number.
    • sqrt(): Calculates the square root of a number.
    • pow(): Raises a number to a power.
    • sin(): Calculates the sine of an angle in radians.
    • cos(): Calculates the cosine of an angle in radians.
    • tan(): Calculates the tangent of an angle in radians.
    • floor(): Returns the greatest integer less than or equal to a number.
    • ceil(): Returns the smallest integer greater than or equal to a number.
  • String manipulation functions:
    • strlen(): Returns the length of a string.
    • strcpy(): Copies one string to another string.
    • strcat(): Concatenates two strings.
    • strcmp(): Compares two strings and returns an integer value indicating whether they are equal, less than, or greater than each other.
  • Input/output functions:
    • cin: Reads data from the standard input stream.
    • cout: Writes data to the standard output stream.
    • cerr: Writes data to the standard error stream.
    • fopen(): Opens a file for reading or writing.
    • fclose(): Closes a file.

Example 1:

cout << sqrt(18) << endl;

Output:

4.24264

Example 2:

cout << abs(-18) << endl;

Output:

18

Example 3:

cout << mod(10.5,2) << endl;

Output:

0.5

Example 4:

cout << floor(10.2) << endl;

Output:

10

Example 5:

cout << floor(-10.2) << endl;

Output:

-11

Example 6:

cout << ceil(10.2) << endl;

Output:

11

Example 7:

#include <iostream>

using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

To use a built-in function, you simply need to include the appropriate header file. So you might have a problem executing this program. you would need to include the <cmath> header file.

The <cmath> header file contains declarations for a number of mathematical functions, such as sqrt(), pow(), sin(), cos(), and tan(). These functions are useful for performing common mathematical operations, such as calculating the square root of a number, raising a number to a power

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

Output:

3

Example 8:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(10,5) << endl;

    return 0;
}

You would need to include the <algorithm> header file to use any of the algorithms provided by the C++ standard library. These algorithms include sorting, searching, merging, and many more.

Output:

10

Example 9:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(15,max(10,5)) << endl;

    return 0;
}

Output:

15

Example 10:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    
    int x = 0, y = 10;
    swap(x,y);
    cout << "x= " << x << "y= " << y << endl;

    return 0;
}

Output:

x= 10y= 0

Built-in functions can be a very useful tool for C++ programmers. By using built-in functions, you can avoid having to write your own code for common tasks.

 

 

Function part 4 (Random functions)

Random functions in C++ are used to generate random numbers. There are two built-in random functions in C++: rand() and srand().

The rand() function generates a random integer between 0 and RAND_MAX, where RAND_MAX is a macro that is defined in the cstdlib header file. The srand() function is used to seed the random number generator. If you don’t call srand(), the random number generator will be seeded with a default value.

Example 1:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    
    cout << rand() << endl;
    
    return 0;
}

This code prints a random integer to the console.

Example 2:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand() << endl;
    }
    
    return 0;
}

This code is a for loop that prints 10 random integers to the console.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand()%10 << endl;
    }
    
    return 0;
}

This code generates a random number between 0 and 9 and prints it to the console. The modulus operator (%) returns the remainder of a division operation. So, the expression rand()%10 will return the remainder of the operation rand() / 10. This will give us a number between 0 and 9.

Example 4:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

This code generates a random number between 20 and 30 and prints it to the console.

Example 5:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(time(0));
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

The srand(time(0)); function seeds the random number generator with the current time. This ensures that the random numbers are different each time the program is run.

The srand() function takes an integer seed as its argument and initializes the random number generator with that seed. The time(0) function returns the current time as a time_t value, which is an integer.

By seeding the random number generator with the current time, we are using a value that is constantly changing, which ensures that the random numbers are different each time the program is run.

It is important to seed the random number generator before using the rand() function. If you do not seed the random number generator, it will be seeded with a default value, which will result in the same sequence of random numbers being generated each time the program is run.

Example 6:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    int x, y;
    x = time(0);
    for (size_t i = 0; i < 10000; i++)
    {
        cout << time(NULL) << endl;
        y = time (0);
    }
    cout << "The token time:" << y - x << endl;
    return 0;
}

This code prints the current time 10000 times to the console and then prints the total time it took to do so.

The program works as follows:

  1. The int x, y; declaration creates two integer variables, x and y.
  2. The x = time(0); statement assigns the current time to the variable x.
  3. The for (size_t i = 0; i < 10000; i++) loop iterates 10000 times.
  4. On each iteration of the for loop, the following code is executed:
    • The current time is printed to the console using the cout << time(NULL) << endl; statement.
  5. The y = time(0); statement assigns the current time to the variable y.
  6. The cout << "The token time:" << y - x << endl; statement prints the total time it took to print the current time 10000 times to the console.

The time(NULL) function is a synonym for the time(0) function.

You can use this code to measure the performance of your code or to calculate the elapsed time between two events.

Function part 5 (Call By Reference vs Call By Value)

Call by value and call by reference are two different ways to pass arguments to functions in C++.

Call by value is the default passing mechanism in C++. When a function is called by value, a copy of the actual argument is passed to the function. The function then operates on this copy, and any changes made to the copy inside the function will not be reflected in the actual argument outside the function.

Call by reference allows you to pass the reference of the actual argument to the function. This means that the function operates directly on the actual argument outside the function. Any changes made to the argument inside the function will be reflected in the actual argument outside the function.

To pass an argument by reference, you need to use the & operator before the argument name

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void swap(int x, int y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 10 y= 20

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void swap(int&x, int&y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 20 y= 10

As you can see, the result of calling the swap() function is different depending on whether it is called by value or by reference.

Call by reference is often used to modify the values of the arguments outside the function. For example, the swap() function could be used to swap the values of two variables.

Call by reference can also be used to pass large objects to functions without having to copy them. This can improve the performance of your program.

However, it is important to use call by reference carefully, as it can lead to unexpected results if not used correctly. For example, if you pass a reference to a local variable to a function, and the function returns, the local variable will go out of scope, but the reference to it will still be valid. This can lead to a program crash if you try to access the local variable through the reference.

In general, it is best to use call by value unless you have a specific reason to use call by reference.

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void fun(int x, int y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 50 R= 10

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void fun(int&x, int&y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 51 R= 12

As you can see, the result of calling the fun() function is different depending on whether it is called by value or by reference.

Function part 6 (Recursion 1)

Recursion is a programming technique where a function calls itself directly or indirectly. This can be used to solve problems that can be broken down into smaller, simpler problems of the same type.

Recursion can be a bit difficult to understand at first, but it is a powerful tool that can be used to solve a wide variety of problems.

Here is a simple example of a recursive function in C++:

#include <iostream>
using namespace std;
void f(int n)
{
    if (n < 1)
        return;
    else
        cout << "round:" << n << endl;
    f(n - 1);
}

int main()
{
    f(5);
    return 0;
}

The function f(int n) is a recursive function that prints the string “round:” followed by the integer n to the console n times.

The function works by recursively calling itself to print the string “round:” followed by the integer n - 1 to the console. This process continues until n is equal to 1, at which point the function returns.

Output:

round: 5
round: 4
round: 3
round: 2
round: 1

Recursive functions can be a bit difficult to understand at first, but they are a powerful tool that can be used to solve a wide variety of problems.

You should pay attention to these 3 contents of a recursive function (base case, logic and subproblem), which are marked in the following function:

void f(int n)
{
    if (n < 1)
        return; //base case
    else
        cout << "round:" << n << endl; //logic
    f(n - 1); //subproblem
}

The three contents of a recursive function are:

  • Base case: The base case is a special case that is handled directly in the function without making any recursive calls. The base case is usually a simple case that can be solved directly.
  • Logic: The logic of a recursive function is the code that is executed to break down the problem into smaller, simpler problems of the same type. The logic usually involves making recursive calls to the function with smaller input values.
  • Subproblem: A subproblem is a smaller, simpler problem of the same type as the original problem. Recursive functions work by breaking down the original problem into subproblems and then solving the subproblems using the same recursive function.

Here is an example of a recursive function in C++ that calculates the factorial of a number:

#include <iostream>
using namespace std;
int fact(int n)
{
    if (n == 0 || n == 1)
        return 1;
    else
        return n*fact(n - 1);
}

int main()
{
    cout << fact(5) << endl;
    return 0;
}

The function fact(int n) is a recursive function that calculates the factorial of a number. The factorial of a number is the product of all the positive integers less than or equal to that number. For example, the factorial of 5 is 120, because 120 is the product of 1, 2, 3, 4, and 5. So, the  output of our program will be 120.

The function fact(int n) works by recursively calling itself to calculate the factorial of the number one less than the input number. For example, to calculate the factorial of 5, the function would first call itself to calculate the factorial of 4. This would then call itself to calculate the factorial of 3, and so on. Eventually, the function would reach the base case, where the input number is 0 or 1. The base case is a special case that is handled directly in the function without making any recursive calls. The factorial of 0 is 1 and the factorial of 1 is also 1, so the function simply returns 1 in these cases.

Fibonacci Series

The Fibonacci sequence is a series of numbers where each number is the sum of the two previous numbers. The first two numbers in the sequence are 0 and 1, and each subsequent number is the sum of the previous two numbers.

Here is the Fibonacci sequence up to the first 10 numbers:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The Fibonacci sequence can be generated using the following recurrence relation:

F(n) = F(n - 1) + F(n - 2)

where F(n) is the nth number in the Fibonacci sequence.

The Fibonacci sequence has a number of interesting properties. For example, the ratio of successive Fibonacci numbers approaches the golden ratio as the numbers get larger. The golden ratio is an irrational number that is approximately equal to 1.618.

The Fibonacci sequence appears in many different areas of mathematics and nature. For example, it can be used to model the growth of a population of rabbits, the spiral pattern of a seashell, and the branching pattern of a tree.

Here are some examples of how the Fibonacci sequence is used in the real world:

  • Finance: The Fibonacci sequence can be used to identify potential support and resistance levels for stock prices.
  • Music: The Fibonacci sequence can be used to create musical compositions with a pleasing rhythm and structure.
  • Art: The Fibonacci sequence can be used to create works of art with a balanced and harmonious composition.
  • Architecture: The Fibonacci sequence can be used to design buildings and other structures that are aesthetically pleasing and structurally sound.

The Fibonacci sequence is a fascinating and versatile mathematical sequence that has many applications in the real world.

Example:

#include <iostream>
using namespace std;
int fib(int n)
{
    if (n == 0 || n == 1)
        return n;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    cout << fib(3) << endl;
    return 0;
}

The function fib(int n) works by recursively calling itself to calculate the Fibonacci numbers of the previous two numbers. If the input number n is 0 or 1, the function simply returns the number, because the first two Fibonacci numbers are 0 and 1. Otherwise, the function returns the sum of the Fibonacci numbers of the previous two numbers.

Output:

2

 

Function part 7 (Recursion 2)

Example 1:

#include <iostream>
using namespace std;
int sum(int n)
{
    if (n == 1)
        return 1;
    else
        return n + sum(n - 1);
}

int main()
{
    cout << sum(5) << endl;
    return 0;
}

This function calculates the sum of the first n natural numbers. The first n natural numbers are the numbers from 1 to n.

The function works by recursively calling itself to calculate the sum of the first n - 1 natural numbers. If the input number n is 1, the function simply returns the number 1, because the sum of the first natural number is 1. Otherwise, the function returns the sum of the input number n and the sum of the first n - 1 natural numbers.

Output:

15

Example 2:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    if (x == y)
        return x;
    else
        return y + sum(x, y - 1);
}

int main()
{
    cout << sum(4, 6) << endl;
    return 0;
}

This is a recursive function sum. It takes two integer parameters, x and y, which represent the range of numbers to sum. Here’s how the function works:

  • The base case: If x is equal to y, it means we have reached the end of the range, so it returns x. This is the terminating condition for the recursion.
  • The recursive case: If x is not equal to y, it adds the current value of y to the result of calling the sum function again with the same x and y-1. This effectively breaks down the sum of the range into smaller subproblems by reducing the upper bound (y) by 1 in each recursive call.

In the main function, it calls the sum function with the arguments 4 and 6 and then outputs the result to the console using cout. In this case, it will calculate the sum of integers from 4 to 6 (inclusive) and print the result.

When you run this code, it will output the sum of integers from 4 to 6, which is 4 + 5 + 6 = 15. So, the output of this code will be:

15

Function part 8 (Overloading Function)

Function overloading is a feature of C++ that allows you to have two or more functions with the same name, as long as they have different parameters. This can be useful when you want to have a single function that can perform different tasks, depending on the type of data that is passed to it as an argument.

For example, this code is a set of three C++ functions that print different types of data to the console.

#include <iostream>
using namespace std;

void print(int a)
{
    cout << "Integer = " << a << endl;
}
void print(float a)
{
    cout << "Float = " << a << endl;
}
void print(char c)
{
    cout << "Character = " << c << endl;
}

int main()
{
    print(1);
    print('a');
    return 0;
}

The first function, print(int a), takes an integer as an argument and prints it to the console with the prefix “Integer = “.

The second function, print(float a), takes a floating-point number as an argument and prints it to the console with the prefix “Float = “.

The third function, print(char c), takes a character as an argument and prints it to the console with the prefix “Character = “.

Output:

Integer = 1
Character = a

 

Function part 9 (Default arguments)

Default arguments are a feature of C++ that allows you to specify a default value for a function parameter. This means that if a caller of the function does not provide a value for a particular parameter, the default value will be used instead.

Default arguments can be useful for simplifying the code that calls a function, and for making the function more flexible. For example, you could have a function that takes two parameters, but where the second parameter is optional. You could then specify a default value for the second parameter, so that callers of the function do not have to provide a value for it if they do not want to.

Here is an example of how to use default arguments in C++:

#include <iostream>
using namespace std;

int sum(int a = 5, int b = 5, int c = 5)
{
    return a + b + c;
}

int main()
{
    cout << sum(10, 55) << endl;
    return 0;
}

This code calculates the sum of three integers. The program uses default arguments to provide default values for the three integers. This means that if the caller of the sum() function does not provide values for all three integers, the default values will be used instead.

The main() function calls the sum() function with the arguments 10 and 55. The sum() function will then return the sum of the three integers, which is 70. The main() function will then print the result to the console.

Output:

70

Here are some tips for using default arguments:

  • Do not write your default argument in the middle of two arguments like this (int a, int b = 5, int c), it will produce an error to the compiler.
  • Be careful not to overwrite default parameters with values that are not valid for the function.
  • Use default parameters to provide default values for parameters that are not essential to the function’s functionality.

Function part 10 (Inline Function)

An inline function in C++ is a function whose code is substituted at the point of call. This means that the compiler copies the code of the inline function into the calling function, instead of generating a call instruction.

Inline functions are typically used for small functions that are frequently called. This can improve the performance of the program, as it eliminates the overhead of function calls.

To declare an inline function in C++, you use the inline keyword before the function declaration. For example:

#include <iostream>
using namespace std;

inline void p()
{
    cout << "hello" << endl;
}

int main()
{
    p();
    p();
    p();
    return 0;
}

inline void p(), defines an inline function called p(). The function takes no arguments and simply prints the word “hello” to the console, followed by a newline character.

The three lines, p();, p();, and p();, call the p() function three times.

When the program is executed, the following output will be printed to the console:

hello
hello
hello

It is important to note that the compiler is not obligated to inline a function, even if it is declared as inline. The compiler may choose not to inline a function if it is too large or if it is called indirectly.

Here are some of the benefits of using inline functions:

  • Improved performance: Inline functions can improve the performance of a program by eliminating the overhead of function calls.
  • Reduced code size: Inline functions can reduce the code size of a program by removing the need to generate separate code for each function call.
  • Increased readability: Inline functions can make code more readable by eliminating the need to jump back and forth between different functions.

However, there are also some potential drawbacks to using inline functions:

  • Increased compile time: Inlining functions can increase the compile time of a program, as the compiler needs to copy the code of the inline function into each calling function.
  • Increased code size: If an inline function is called frequently, it can increase the code size of the program.
  • Reduced maintainability: Inline functions can make code more difficult to maintain, as the code for the inline function is scattered throughout the program.

Overall, inline functions can be a useful tool for improving the performance and readability of code. However, it is important to use them carefully, as they can also increase the compile time and code size of a program.

Here are some tips for using inline functions effectively:

  • Only inline small functions that are frequently called.
  • Avoid inlining functions that are too large or that are called indirectly.
  • Use the inline keyword consistently, so that the compiler can make informed decisions about whether or not to inline a function.
  • Document your code clearly, so that other developers understand how and why inline functions are being used.

Static variable

A static variable in C++ is a variable that is allocated once and remains in memory throughout the execution of the program. Static variables can be declared at global scope, namespace scope, class scope, or function scope.

Static variables at global scope are initialized when the program starts and are destroyed when the program ends. Static variables at namespace scope are initialized when the namespace is loaded and are destroyed when the namespace is unloaded. Static variables in classes are initialized when the class is first used and are destroyed when the program ends. Static variables in functions are initialized when the function is first called and are destroyed when the function returns.

Static variables can be useful for a variety of purposes, such as:

  • Storing global state information: Static variables can be used to store global state information that needs to be accessed by multiple functions in a program.
  • Implementing singletons: Static variables can be used to implement singletons, which are classes that can only have one instance.
  • Implementing lazy initialization: Static variables can be used to implement lazy initialization, which is a technique for delaying the initialization of a variable until it is first used.

Here is an example of a static variable declared in a function:

#include <iostream>
using namespace std;

void fun()
{
    static int x = 0;
    x++;
    cout << x << endl;
}

int main()
{
    fun();
    fun();
    return 0;
}

This code is a C++ program that defines a function called fun() and then calls it twice from the main() function. The fun() function declares a static variable called x and increments it each time it is called. The function then prints the value of x to the console.

Because x is a static variable, its value is preserved between function calls. This means that when the fun() function is called the second time, the value of x will be 1, not 0. Therefore, the output of the program will be as follows:

1
2

This code demonstrates how static variables can be used to store state information that needs to be accessed by multiple function calls.

Aliasing & Constant Variable

Aliasing

Aliasing in C++ is when two or more different names refer to the same memory location. This can happen when you use pointers or references, or when you declare two variables of the same type and initialize them to the same value.

For example, the following code creates an alias to the variable x:

int x = 1;
int &y = x;

Now, both the variables x and y refer to the same memory location. If you change the value of x, the value of y will also change.

Example:

#include <iostream>
using namespace std;

int main()
{
    int x = 1;
    int &y = x;
    x = 5;
    int &z = y;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = 7;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = x + z - 3;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;

    return 0;
}

The code begins by declaring an integer variable named x and initializing it to 1. Then, it declares an integer reference named y and binds it to the variable x. This means that y is now an alias for x.

Next, the code assigns the value 5 to the variable x. This also changes the value of the variable y, since it is an alias for x.

Then, the code declares another integer reference named z and binds it to the variable y. This means that z is also an alias for x.

Now, all three variables x, y, and z refer to the same memory location. This means that changing the value of any one of these variables will also change the value of the other two variables.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 5 y = 5 z = 5

Next, the code assigns the value 7 to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 7 y = 7 z = 7

Finally, the code calculates the value of x + z - 3 and assigns it to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 11 y = 11 z = 11

This code demonstrates how aliasing can be used to change the values of multiple variables at once. It also demonstrates how aliasing can be used to create aliases for complex expressions.

It is important to note that aliasing can be a powerful tool, but it can also lead to confusion and errors if used incorrectly. It is important to carefully consider the implications of aliasing before using it in your code.

Constant Variable

A constant variable in C++ is a variable whose value cannot be changed after it is initialized. To declare a constant variable, you use the const keyword before the variable type. For example:

const double Pi = 3.14;

Once you have declared a constant variable, you cannot assign a new value to it. If you try to do so, the compiler will generate an error.

Example:

#include <iostream>
using namespace std;

int main()
{
    const double Pi = 3.14;
    int r;
    cout << "please enter r: ";
    cin >> r;
    double a = Pi * r * r;
    cout << "Area of circle = " << a << endl;

    return 0;
}

This code calculates the area of a circle. The program begins by declaring a constant double variable named Pi and initializing it to the value 3.14. Then, it declares an integer variable named r and prompts the user to enter a value for it.

Next, the program calculates the area of the circle using the following formula:

  • Area = πr²

The program then prints the area of the circle to the console.

Here is a breakdown of the code:

int main()
{
  // Declare a constant double variable named Pi and initialize it to the value 3.14.
  const double Pi = 3.14;

  // Declare an integer variable named r.
  int r;

  // Prompt the user to enter a value for r.
  cout << "please enter r: ";
  cin >> r;

  // Calculate the area of the circle.
  double a = Pi * r * r;

  // Print the area of the circle to the console.
  cout << "Area of circle = " << a << endl;

  return 0;
}

Output:

please enter r: 5
Area of circle = 78.5

Aliasing and constant variables can interact in a few interesting ways:

  • If you have a constant variable and you create an alias to it, the alias is also constant. This is because the alias is just another name for the same variable, and the value of the variable cannot be changed.
  • If you have a constant variable and you pass it to a function as a parameter, the function cannot change the value of the variable. This is because the function is only allowed to modify the local copy of the variable.
  • If you have a pointer to a constant variable, you can still use the pointer to dereference the variable and read its value. However, you cannot use the pointer to change the value of the variable.

Here is an example of aliasing and constant variables in C++:

#include <iostream>
using namespace std;

int main()
{
    int i = 1;
    int &j = i;
    cout << "j = " << j << endl;
    const int &k = j;
    cout << "k = " << k << endl;

    return 0;
}

Output:

j = 1
k = 1

 

One Dimensional Array (part 1)

An array is a data structure that stores a collection of elements of the same data type. These elements are stored in contiguous memory locations, and they can be accessed using an index. Arrays provide a way to manage and manipulate a large set of data efficiently.

In C++, you can declare an array by specifying its data type and the number of elements it will hold. Here’s a basic syntax:

data_type array_name[array_size];

Arrays in C++ are zero-indexed, meaning the first element is accessed using the index 0, the second element with index 1, and so on. You can access and modify array elements using square brackets:

array_name[index] = new_value;

Here is an example:

#include <iostream>
using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 20;
    cout << x[0] << endl;
    x[2];
    x[3];
    x[4];

    return 0;
}

1. int x[5];

This line declares an integer array named x with a size of 5. It means that x can store five integer values. However, at this point, the values in the array are uninitialized, which means they contain random data.
2. x[0] = 10;

Here, we assign the value 10 to the first element of the array x. In C++, arrays are zero-indexed, so x[0] refers to the first element.
3. x[1] = 20;

Similarly, we assign the value 20 to the second element of the array x, which is x[1].
4. cout << x[0] << endl;

This line prints the value of the first element of the array x, which is 10, to the console. It uses the cout object from the C++ Standard Library to output the value, followed by an end-of-line character (endl) for formatting.
5. x[2];

These lines appear to be accessing the third element of the array x, but they don’t do anything. It’s essentially a “noop” operation, and the value in x[2] remains uninitialized or unchanged.
6. x[3]; and x[4];

Similar to the previous line, these lines access the fourth and fifth elements of the array x, but they also don’t perform any meaningful operation.

Output:

10

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 5;
    x[4] = x[0] + x[1];
    cout<< x[4] << endl;

    return 0;
}

Output:

15

Arrays only accept constant array size, Example:

#include <iostream>

using namespace std;

int main()
{
    const int t = 5;
    int x[t];

    return 0;
}

This code declares an integer array `x` with a size of 5, and the size is determined by the constant `t`, which is set to 5. The `const` keyword ensures that `t` cannot be changed later in the program. This code doesn’t perform any further operations on the array; it simply demonstrates how to declare an array with a size determined by a constant.

You can also declare the size of your array, and declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = { 1,4,8,7,2 };
    cout << x[0] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes it with the values 1, 4, 8, 7, and 2. It then prints the first element of the array, which is 1, to the console. This code demonstrates how to create an array and access its elements in C++.

But what if you declared no initial values into your array?

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 but does not initialize its elements. Therefore, when you attempt to print the value of the fourth element, it will display a random or garbage value. It’s important to initialize array elements before using them to avoid unpredictable behavior in your programs.

What if you declared only one initial value that equals to 0?

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {0};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes all its elements to 0. It then prints the value of the fourth element of the array, which is 0, to the console. This code demonstrates how to create an array with specific initial values in C++.

You can also declare a size of array and declare some of the first initial values, for example:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {1,2,3};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes the first three elements with values, while the remaining two elements are automatically initialized to 0. It then prints the value of the fourth element, which is 0, to the console.

Or, you can declare no size of your array and only declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[] = {1,2,3,4,5};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x and initializes it with values using an array initialization list. It then prints the value of the fourth element of the array, which is 4, to the console. This code demonstrates how to create an array and access its elements in C++.

How does the compiler store the values on an array?

The compiler stores the values of an array in contiguous memory locations. This means that the values of the array elements are stored next to each other in memory. The compiler allocates a block of memory that is large enough to store all of the array elements, and then it stores the values of the elements in this block of memory.

The compiler keeps track of the address of the first element in the array, and then it uses this address to access the other elements in the array. For example, to access the element at index i, the compiler adds i to the address of the first element.

The specific way that the compiler stores the values of an array depends on the data type of the array elements. For example, if the array elements are integers, the compiler will store each integer in a single memory location. However, if the array elements are structs, the compiler will store each struct in a contiguous block of memory locations.

This code shows you how to read and store user input in an array in C++, it allows the user to input an integer value for the first element of an array, arr[0], and then it displays the value that was entered.

#include <iostream>

using namespace std;

int main()
{
    int arr[50];
    cout << "Enter arr[0]: " << endl;
    cin >> arr[0];
    cout << arr[0] << endl;

    return 0;
}

 

To traverse the elements of an array, you can use loops like for or while. Looping through an array allows you to perform operations on each element systematically.

Example:

#include <iostream>

using namespace std;

int main()
{
    int arr[10];
    for (size_t i = 0; i < 10; i++)
    {
        cout << "Enter arr[" << i << "]: ";
        cin >> arr[i];
    }
    for (size_t i = 0; i < 10; i++)
    {
        cout << "arr[" << i << "] = " << arr[i] << endl;
    }

    return 0;
}

This code allows the user to input 10 integer values, one for each element of the array, and then it displays the values along with their indices. It demonstrates how to read and store multiple user inputs in an array and subsequently print the contents of the array in C++.

One Dimensional Array (part 2)

Arrays are incredibly versatile, and you can perform various operations on them, such as copying the initial values of an existing array into another one.

Of course we cannot use the following command:

arr2 = arr1;

Because we aren’t assigning a single value. Each array has a collection of values, so if we need to assign a single value in an array we have to specify its index:

arr2[0] = arr1[0];

But what if we need to assign all the values of an array into another array?

Example 1:

#include <iostream>

using namespace std;

int main()
{
    const int s = 4;
    int arr1[s] = { 10,20,30,40 };
    int arr2[s];

    for (size_t i = 0; i <= s-1; i++)
    {
        arr2[i] = arr1[i];
    }

    for (size_t i = 0; i < s; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    return 0;
}

This code initializes an array arr1 with values, then copies the contents of arr1 into another array arr2. Finally, it prints the elements of arr2. This demonstrates how to copy the contents of one array into another in C++.

Output:

10 20 30 40

Example 2:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,0 };
    int sum = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        //sum += arr[i];
        sum = sum + arr[i];
    }
    cout << "sum = " << sum << endl;

    return 0;
}

This code calculates the sum of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate values.

Output:

sum = 1000

Example 3:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,100 };
    long long d = 1;
    
    for (size_t i = 0; i < s; i++)
    {
        d *= arr[i];
    }
    cout << "multi = " << d << endl;

    return 0;
}
  • long long d = 1; :This line initializes a long long integer variable d to 1. This variable will be used to accumulate the product of the elements in the array.
  • long long is a data type in C++ that represents a 64-bit integer. It’s designed to store very large integer values. It can hold a wider range of values compared to regular int or long integers.
  • So, the statement long long d = 1; declares a variable named d with a data type of long long and initializes it with the value 1. This variable can then be used to store and manipulate large integer values in your program.

In summary, this code calculates the product of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate the product of its elements.

Output:

multi = 200000000000

Example 4:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,501,101 };
    int sumEven, sumOdd = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] % 2 == 0)
            sumEven += arr[i];
        else
            sumOdd += arr[i];
    }
    cout << "Sum of even numbers = " << sumEven << endl;
    cout << "Sum of odd numbers = " << sumOdd << endl;

    return 0;
}

This code calculates the sum of even and odd numbers separately in the integer array arr and then prints the results to the console.

Output:

Sum of even numbers = 500
Sum of odd numbers = 602

Example 5:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int marks[s] = { 100,99,98,88,70,90 };
    int sum = 0;
    for (size_t i = 0; i < s; i++)
    {
        sum += marks[i];
    }
    cout << "Average = " << sum / s << endl;

    return 0;
}

This code calculates the average of the marks stored in the integer array marks and then prints the average to the console.

Output:

Average = 90

Example 6:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int arr[s] = { 22,100,95,101,200,90 };
    int max = 0;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] > max)
            max = arr[i];
    }
    cout << "Maximum number = " << max << endl;

    return 0;
}

This code finds the maximum value among the numbers stored in the integer array arr and then prints the maximum value to the console.

Output:

Maximum number = 200

Example 7:

#include <iostream>

using namespace std;

int main()
{
    int vector[5];
    cout << "Enter 5 numbers: ";
    for (int i = 0; i < 5; i++)
        cin >> vector[i];
    cout << endl;
    
    int Element;
    cout << "What is the element you are looking for? ";
    cin >> Element;
    
    bool Found = false;
    int i;
    for (i = 0; i < 5; i++)
        if (Element == vector[i])
        {
            Found = true;
            break;
        }
    cout << endl;
    if (Found)
        cout << Element << " found at position " << i << endl;
    else
        cout << Element << " is not in this array!" << endl;

    return 0;
}

In this C++ code, you’re taking user input to populate an integer array `vector` of size 5 and then searching for a specific element within the array. Let’s break down the code step by step:

  1. int vector[5];
    – This line declares an integer array `vector` with a size of 5, which can store up to five integer values.
  2. Input Loop to Populate the Array:
    – The code prompts the user to enter five numbers and stores them in the `vector` array using a `for` loop that iterates five times. Each input is assigned to a different element of the array.
  3. int Element;
    – This line declares an integer variable `Element`, which will store the value the user is searching for.
  4. Prompt for the Element to Search:
    – The code asks the user to input the element they want to search for.
  5. Search Loop:
    – The `for` loop is used to search for the element within the array. If the element is found, the loop breaks, and the `Found` flag is set to `true`. The variable `i` keeps track of the position where the element was found.
  6. Output the Result:
    – The code then checks if the element was found (i.e., `Found` is `true`). If found, it displays the element and its position in the array. If not found, it informs the user that the element is not in the array.

In summary, this code allows the user to enter five numbers into an array and then search for a specific element within the array. It provides feedback on whether the element was found and its position in the array.

One Dimensional Array part 3 (Passing Array To Function)

In C++, you can pass an array to a function, and this is a fundamental concept when working with arrays. When you pass an array to a function, you’re essentially allowing that function to operate on the array’s elements or modify the array if needed.

Here’s an explanation of how to pass an array to a function in C++:

Array Declaration in a Function

Array Parameters: To pass an array to a function, you need to declare the function parameter as an array. You can declare it in two ways:

  • Using a Fixed Size: If you know the size of the array in advance, you can specify the size in the function parameter, like this:
void functionName(int arr[5]) {
    // Code to work with the array
}
  • Using a Pointer: You can also declare the function parameter as a pointer to the array’s elements without specifying the size, like this:
void functionName(int *arr, int size) {
    // Code to work with the array
}

In this case, you pass the size of the array as a separate argument.

Passing the Array to the Function

Calling the Function: When you call the function, you provide the array as an argument. If you declared the function parameter with a fixed size, you pass the array directly. If you used a pointer, you pass the array and its size as arguments.

Example with a fixed-size array parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray);

Example with a pointer parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray, 5);

Using the Array in the Function

Working with the Array: Inside the function, you can access and manipulate the elements of the array as needed. You can use array indices (e.g., arr[0], arr[1]) to access individual elements, and you can use loops to iterate through the elements.

Example of accessing array elements:

void functionName(int arr[5]) {
    for (int i = 0; i < 5; i++) {
        // Access and manipulate arr[i]
    }
}

Here is a demonstration of passing an array to functions for setting values in the array and then printing those values:

#include <iostream>
using namespace std;

void set(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << "Enter array value: ";
        cin >> arr[i];
    }
}

void print(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << arr[i] << " ";
    }
}

int main()
{
    int a[5];
    set(a, 5);
    print(a, 5);

    return 0;
}

The set function allows the user to set values in the array, and the print function prints the values stored in the array. It’s a practical example of how to work with arrays and functions in C++.

Modifying the Array

Example 1:

This code shows an implementation of the “Bubble Sort” algorithm. Bubble Sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, indicating that the list is sorted. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

int main()
{
    int vector[] = {6,5,4,1,2};
    int t = 0;
    
    // Bubble Sort algorithm
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (vector[j] > vector[j + 1])
            {
                t = vector[j];
                vector[j] = vector[j + 1];
                vector[j + 1] = t;   
            }
        }
    }
    
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }

    return 0;
}
  1. int vector[] = {6, 5, 4, 1, 2};:
    An integer array vector is initialized with unsorted values.
  2. int t = 0;:
    An integer variable t is declared to be used for swapping elements during the sorting process.
  3. Bubble Sort Algorithm:
    The nested for loops are used to implement the Bubble Sort algorithm. The outer loop (i) controls the number of passes, and the inner loop (j) compares adjacent elements and swaps them if they are out of order.
  4. If the element at index j is greater than the element at index j + 1, a swap is performed to put them in ascending order.
  5. Printing the Sorted Array:
    After sorting is complete, the code uses a for loop to print the sorted elements in ascending order.

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array. Bubble Sort is not the most efficient sorting algorithm for large data sets, but it’s easy to understand and implement.

Example 2:

This code performs the sorting of an integer array using the Bubble Sort algorithm. It sorts the array in ascending order and then prints the sorted values. Let’s break down the code step by step:

#include <iostream>
using namespace std;

const int s = 5;
void sort(int arr[])
{
    int t = 0;
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;   
            }
        }
    }
}

void print(int vector[])
{
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }
}

int main()
{
    int vector[] = {0,-1,55,-5,-100};
    sort(vector);
    print(vector);
    return 0;
}

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array.

Example 3:

This code demonstrates how to reverse the elements of an integer array using a reversArray function. It reverses the array in-place and then prints the reversed array:

#include <iostream>
using namespace std;

void reversArray(int arr[], int s)
{
    for (size_t i = 0; i < s / 2; i++)
    {
        swap(arr[i], arr[s - i - 1]);
    }
}

int main()
{
    int vector[] = {3,2,4,5,6};
    reversArray(vector, 5);
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << " ";
    }

    return 0;
}

The output of this code will be the reversed array, where the elements are reversed in place. This is achieved by swapping the first element with the last element, the second element with the second-to-last element, and so on. It’s a simple and efficient way to reverse the order of elements in an array.

 

Note:

If you don’t want to modify your array you can initial its value as a constant in the function. Example:

void print(const int arr[], int s)
{
    //body of the function
}

This way any try to modify the array will produce an error.

One Dimensional Array part4 (Array Of Character)

An array of characters in C++ is often referred to as a “string.” It is a fundamental data structure used to store sequences of characters, such as words, sentences, or even individual characters. In C++, strings are represented as arrays of characters, terminated by a special null character, ‘\0’, which indicates the end of the string.

to initiate a character we use a single quotation like this ‘L’.

Example 1:

char ch[5] = { 'a','b','c','d','e','\0' };

The null character (‘\0’), NULL or 0, is used to indicate the end of the string. This character is automatically added to the end of string literals and is crucial for various string manipulation functions.

If you add characters after the null character they won’t be read by the program.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    char ch[5];
    cin >> ch;
    cout << ch << endl;
    return 0;
}

This code reads a sequence of characters into a char array and then prints the array. However, there are a few things to note about potential issues and improvements in the code:

  1. Array Size:
    The char array ch has a size of 5. If you enter more than 4 characters, it will result in a buffer overflow, causing undefined behavior. It’s essential to ensure that the input doesn’t exceed the array size.
  2. Input Method:
    When using cin >> ch, it reads characters until it encounters whitespace. If you want to read an entire line (including spaces), you should use cin.getline(ch, size) or cin.get(ch, size).

Example 3:

#include <iostream>
using namespace std;

int main() {
    char ch[10];

    // Read up to 9 characters into the char array
    cin.get(ch, 10);

    // Output the char array
    cout << ch << endl;

    return 0;
}

This code reads up to 9 characters (plus the null terminator) into a char array using cin.get() and then prints the array.
Here are a few points to note:

  1. Array Size:
    The char array ch has a size of 10. Since cin.get() reads up to one less than the specified size (leaving space for the null terminator), it effectively reads up to 9 characters.
  2. Input Method:
    cin.get(ch, 10) reads characters until either 9 characters are read, the newline character is encountered, or the end of file is reached. It stops reading after reaching the specified number of characters or encountering one of these conditions.
  3. Null Terminator:
    The array is not explicitly null-terminated by cin.get(); however, C++ streams automatically append a null terminator at the end of the string when reading into a character array. Therefore, the array ch is effectively treated as a C-style string.

Output:

The cout << ch << endl; statement prints the contents of the char array, treating it as a null-terminated string. If fewer than 9 characters were entered, it prints the characters entered. If 9 characters were entered, it prints those 9 characters followed by the null terminator.

Input Limitation:

Keep in mind that the user input is limited to 9 characters, and exceeding this limit may lead to unexpected behavior. It’s essential to handle potential input overflows based on the specific requirements of your program.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char ch1[10], ch2[10];
    cin.getline(ch1, 10);
    cin.getline(ch2, 10);
    cout << ch1 << endl;
    cout << ch2 << endl;
    return 0;
}

This code reads two lines of input into separate char arrays and then prints each array on a new line.

Here are some points to note:

  1. Array Size:
    Both ch1 and ch2 are char arrays with a size of 10. The cin.getline() function reads characters until it encounters a newline character or reaches the specified size (leaving space for the null terminator).
  2. Input Limitation:
    The user input for each line is limited to 9 characters, and the null terminator is automatically added by cin.getline().
  3. Handling Spaces:
    Unlike cin >>, cin.getline() reads the entire line, including spaces. This allows you to input strings with spaces.

Output:

The cout << ch1 << endl; statement prints the contents of the first char array, treating it as a null-terminated string.
Similarly, cout << ch2 << endl; prints the contents of the second char array.
Newline Character:

Each call to cin.getline() reads until it encounters a newline character or reaches the specified size. The newline character is consumed but not stored in the arrays.
This code allows you to input two lines of text (up to 9 characters each) and then prints each line on a new line. It’s suitable for reading and displaying multiple lines of text, handling spaces, and avoiding buffer overflow issues.

 

There are some functions that are part of the C Standard Library and are used for manipulating C-style strings, which are arrays of characters. Here’s an explanation of each function:

  • strcpy (String Copy):

Description: The strcpy function is used to copy the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4];
    strcpy_s(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcpy_s Function:
    The strcpy_s function is part of the C Standard Library and is designed to provide safer string copying by including a size check.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes three characters for the content of ch1 (“AAA”) and one additional space for the null terminator (‘\0’).
  3. Safe String Copy:
    Unlike the standard strcpy function, strcpy_s requires you to provide the size of the destination array (destsz). It checks if there is enough space in the destination array to accommodate the source string and the null terminator. If there isn’t enough space, the function does not perform the copy and returns an error code.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2, which should be “AAA” in this case.

By using strcpy_s, you are taking steps to prevent buffer overflow issues that could occur if the destination array is not large enough to hold the contents of the source string. This is a good practice for enhancing the safety and robustness of your code.

  • strcat (String Concatenate):

Description: The strcat function is used to concatenate (append) the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4] = "HH";
    strcat(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcat Function:
    The strcat function is part of the C Standard Library and is used to concatenate the contents of one C-style string to another.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes two characters (“HH”) and one additional space for the null terminator (‘\0’).
  3. Concatenation:
    The strcat(ch2, ch1); line appends the contents of ch1 to the end of ch2. It starts copying characters from the null terminator of ch2 to the end of ch1 until it encounters the null terminator of ch1. The null terminator of ch2 is updated accordingly.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2 after the concatenation. Since the size of ch2 is limited to 4, it can hold “HH” and the null terminator, but only one additional character from ch1 (“A”) can be accommodated.
Result:

The output of this code is “HHA”, which is the result of concatenating “AAA” to the end of the existing content in ch2.
It’s important to ensure that the destination array has enough space to accommodate the concatenated string, and using functions like strcat requires careful management of buffer sizes to prevent buffer overflows.

  • strcmp (String Compare):

Description: The strcmp function is used to compare two C-style strings lexicographically.

The strcmp function returns an integer value indicating the lexicographic relationship between the two strings. It returns:
– 0 if the strings are equal,
– a negative value if str1 is lexicographically less than str2,
– a positive value if str1 is lexicographically greater than str2.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    cout << strcmp("abc", "abc") << endl;
    return 0;
}

Output:

The cout statement outputs the result of the comparison using strcmp. In this case, since the strings are equal, the output will be 0.

The strcmp function is commonly used for sorting strings, dictionary operations, and other scenarios where you need to determine the lexicographic order of strings. It’s important to handle the result appropriately based on your specific requirements in the program.

  • strlen (String Length):

Description: The strlen function is used to determine the length of a C-style string.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch[] = "jjjjjjjjjjjjjjjjjjjjj";
    cout << strlen(ch) << endl;
    return 0;
}

Output:

The cout statement outputs the result of strlen(ch), which is the length of the string “jjjjjjjjjjjjjjjjjjjjj”. Since there are 21 characters in the string, the output will be 21.

The strlen function is useful for obtaining the length of strings, and it’s important to note that the length does not include the null terminator. Make sure that the string is properly null-terminated to get accurate results with strlen.

 

 

 

 

 

Two Dimensional Array

A two-dimensional array in C++ is a structure that allows you to store elements in a tabular form, organized in rows and columns. It is essentially an array of arrays.

Here’s an explanation of a two-dimensional array in C++:

  • Declaration and Initialization:
// Declaration of a 2D array
int matrix[3][4];

// Initialization of a 2D array
int anotherMatrix[2][3] = { {1, 2, 3}, {4, 5, 6} };
  • Structure:

In a 2D array, elements are arranged in rows and columns. The first index represents the row, and the second index represents the column.

  • Memory Representation:

In memory, a 2D array is stored in a contiguous block of memory. The elements of each row are stored together, and rows are stored one after the other.

  • Accessing Elements:
int value = matrix[1][2];  // Accessing the element in the second row and third column
  • Initialization with Nested Loops:

Common Operations:

– Iterating through elements using nested loops.
– Performing operations on each element.
– Passing a 2D array to functions.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int a[3][4];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 4; j++)
        {
            cin >> a[i][j];
        }
    }
    for (size_t r = 0; r < 3; r++)
    {
        for (size_t c = 0; c < 4; c++)
        {
            cout << a[r][c] << " ";
        }
        cout << endl;
    }
    return 0;
}

This code allows the user to input values into a 2D array a[3][4] and then prints the array in a tabular form.

Here are the key points:

  1. 2D Array Input:
    The nested loops (for loops) are used to iterate over each element of the 2D array and input values using cin.
  2. 2D Array Output:
    Another set of nested loops is used to iterate over each element of the 2D array and output the values using cout.
    The inner loop prints each row, and the outer loop moves to the next row, creating a tabular form.
  3. Tabular Output:
    The cout << a[r][c] << ” “; statement prints each element of the 2D array followed by a space.
    The cout << endl; statement is used to move to the next line after printing each row.
  4. User Interaction:
    The user is prompted to input values for each element of the 2D array. The input is expected to be provided in a row-wise fashion.
  5. Array Size:
    The array a is declared with 3 rows and 4 columns, creating a 3×4 matrix.

This code allows the user to interactively input values into a 3×4 2D array and then displays the array in a tabular format.

Example 2:

#include <iostream>
using namespace std;

int main() {
    // Initialization of a 2D array with predefined values
    int arr[2][4] = {{1, 1, 1, 1}, {2, 2, 2, 2}};
    
    // Variable to store the sum of array elements
    int sum = 0;

    // Nested loops to iterate over each element of the 2D array
    for (size_t r = 0; r < 2; r++) {
        for (size_t c = 0; c < 4; c++) {
            // Accumulate the values to calculate the sum
            sum += arr[r][c];
        }
    }

    // Output the sum of array elements
    cout << "sum = " << sum << endl;

    return 0;
}

Output:

In this specific example, the sum is calculated as follows: 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 = 12.
The output will be sum = 12.

This code is a simple illustration of how to iterate over elements in a 2D array and perform a basic operation, in this case, calculating the sum of all elements.

Example 3:

#include <iostream>
using namespace std;
int main()
{
    int marks[10][5];
    for (size_t r = 0; r < 10; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            cout << "Enter mark " << c + 1 << " " << "for student " << r + 1 << ": " << endl;
            cin >> marks[r][c];
        }
    }
    double s = 0;
    float avg[10];
    for (size_t r = 0; r < 10; r++)
    {
        s = 0;
        for (size_t c = 0; c < 5; c++)
        {
            s += marks[r][c];
        }
        avg[r] = s / 5;
        cout << "Average for student #" << r + 1 << " = "<< avg[r] << endl;
    }
    return 0;
}

This code collects marks for 10 students in 5 subjects, calculates the average mark for each student, and then outputs the average for each student.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char MTXchar[5][5] = {{'*','$','$','$','$'},
                          {'$','*','$','$','$'},
                          {'$','$','*','$','$'},
                          {'$','$','$','*','$'},
                          {'$','$','$','$','*'}};
                          
    for (size_t r = 0; r < 5; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            
            if (c == r)
                cout << MTXchar[r][c];
            else
                cout << " ";
        }
        cout << endl;
    }
    return 0;
}

This code defines a 5×5 matrix (MTXchar) containing ” characters on the main diagonal and ‘$’ characters elsewhere. It then prints only the characters on the main diagonal, resulting in a diagonal line of ” characters.

Output:

The code outputs a diagonal line of ‘*’ characters on the console.

*    
 *   
  *  
   * 
    *

 

Passing a two-dimensional array to a function in C++ involves specifying the array as a parameter in the function declaration. Since a 2D array is essentially an array of arrays, you need to specify the size of the columns (since the rows are implicitly known based on the number of arrays).

  • Function Declaration:

When declaring a function that accepts a 2D array, you need to specify the array parameter along with the size of the columns. The size of the rows is not explicitly specified.

void functionName(int arr[][COLS], size_t rows, size_t cols) {
    // Function logic using arr
}

– int arr[][COLS]: This syntax indicates that the function takes a 2D array of integers with a specified number of columns (COLS).
– size_t rows: This parameter can be used to pass the number of rows in the array.
– size_t cols: This parameter can be used to pass the number of columns in the array

  • Function Call:

When calling the function, you need to provide the actual 2D array along with the number of rows and columns.

int myArray[ROWS][COLS];
functionName(myArray, ROWS, COLS);

– myArray: The name of the 2D array you want to pass.
– ROWS: The number of rows in the array.
– COLS: The number of columns in the array.

Example 5:

#include <iostream>
using namespace std;
void f(int arr[][5], int r)
{
    for (size_t i = 0; i < r; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int main()
{
    int a[2][5] = {1,2,3,4,5,
                   10,20,30,40,50};
    f(a, 2);
    return 0;
}

The function f takes a 2D array (arr) and its number of rows (r) as parameters.
It uses nested loops to iterate over each element of the array and prints the elements in a tabular form.

The main function calls the function f with the 2D array a and the number of rows (2) as arguments.

Output:

The output of this code would be the elements of the 2D array a printed in a tabular form.

The printed output would look like:

1 2 3 4 5 
10 20 30 40 50 
  • Transpose matrix

The transpose of a matrix is an operation that flips the matrix over its diagonal, switching the row and column indices of the matrix. In other words, if the original matrix has elements at position (i, j), the transposed matrix will have the element at position (j, i).

Example 6:

#include <iostream>
using namespace std;
int main()
{
    int arr[3][3];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cin >> arr[i][j];
        }
    }
    cout << "Matrix is: \n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    cout << "Transpose matrix is:\n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[j][i] << " ";
        }
        cout << endl;
    }

    return 0;
}

This code takes user input for a 3×3 matrix, prints the original matrix, and then prints its transpose.

Here are the key points:

  1. Input:
    The nested loops take user input for a 3×3 matrix.
  2. Original Matrix Output:
    After taking input, the code outputs the original matrix.
  3. Transpose Matrix Output:
    Another set of nested loops outputs the transpose of the matrix. It switches the row and column indices.

Example Output:

If the user enters:

1 2 3
1 2 3
1 2 3

The output would be:

Matrix is: 
1 2 3 
1 2 3 
1 2 3 
Transpose matrix is:
1 1 1 
2 2 2 
3 3 3

 

Pointer

In C++, a pointer is a variable that stores the memory address of another variable. Pointers provide a powerful mechanism for working with memory and data structures. They allow direct manipulation of memory addresses and enable efficient memory management.

Declaring Pointers

To declare a pointer, you use the data type followed by an asterisk (*) and the pointer name. For example:

int *ptr; // Declares a pointer to an integer
double *dblPtr; // Declares a pointer to a double

Initializing Pointers

Pointers should be initialized before use. You can initialize a pointer by assigning the address of a variable to it. The address-of operator (&) is used to obtain the memory address of a variable.

int num = 10;
int *ptr = &num; // Initializes ptr with the address of num

Dereferencing Pointers

Dereferencing a pointer means accessing the value stored at the memory address it points to. The dereference operator (*) is used for this purpose.

int num = 10;
int *ptr = &num;

cout << *ptr; // Prints the value stored at the address pointed by ptr

Example 1:

#include <iostream>
using namespace std;

int main() {
    // Declaration of a pointer to an integer
    int *ptr;

    // Declaration and initialization of an integer variable
    int val = 5;

    // Assigning the address of 'val' to the pointer 'ptr'
    ptr = &val;

    // Printing the address stored in the pointer
    cout << ptr << endl;

    // Printing the value stored at the address pointed by 'ptr'
    cout << *ptr << endl;

    // Return 0 to indicate successful execution
    return 0;
}

This code declares a pointer, initializes an integer variable, assigns the address of that variable to the pointer, and then prints both the pointer’s value (memory address) and the value it points to.

Here are the key points:

  1. Pointer Declaration:
    int *ptr;: Declares a pointer to an integer. This pointer is currently uninitialized.
  2. Variable Declaration and Initialization:
    int val = 5;: Declares an integer variable named val and initializes it with the value 5.
  3. Assigning Address to Pointer:
    ptr = &val;: Assigns the memory address of the variable val to the pointer ptr. Now ptr “points” to the memory location of val.
  4. Printing Pointer’s Value (Memory Address):
    cout << ptr << endl;: Prints the memory address stored in the pointer ptr. The address is typically represented in hexadecimal format.
  5. Printing Value at the Address Pointed by Pointer:
    cout << *ptr << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by ptr. Prints the value stored in the variable val.

Output:
If you run this program, the output will be something like:

0x7ffee3c86a4c   // The memory address (this will vary on each run)
5                // The value stored at the memory address

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int *p;
    int v = 9;
    p = &v;
    cout << *p << endl;
    return 0;
}

This code prints the address of the value pointed to by the pointer p using the expressions &*p.

cout << &*p << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by p. The & operator then takes the address of this value. Essentially, &*p is equivalent to just p, so this line prints the memory address stored in the pointer p.

 

Pointer part 2 (Array vs Pointer & Passing Pointer To Function)

Arrays in C++

An array is a collection of elements of the same type stored in contiguous memory locations. In C++, arrays can be of primitive types (int, float, etc.) or user-defined types (structures, classes). Arrays have a fixed size, and the elements are accessed using an index.

int numbers[5] = {1, 2, 3, 4, 5};

Pointers in C++

A pointer is a variable that stores the memory address of another variable. Pointers allow for dynamic memory allocation and manipulation. They are often used for efficient memory management and for accessing elements in arrays.

int x = 10;
int *ptr = &x; // ptr now holds the address of x

Array vs. Pointer

In many contexts, arrays and pointers in C++ exhibit similar behavior. When an array name is used in an expression, it decays into a pointer to its first element. For example:

int arr[3] = {1, 2, 3};
int *ptr = arr; // Equivalent to &arr[0]

However, there are differences:

  • An array variable cannot be reassigned to point to a different memory location, whereas a pointer can.
  • Arrays carry information about their size, while pointers do not inherently know the size of the memory they point to.
  • Arrays can be used with the sizeof operator to determine their size, but pointers alone cannot.

Pointer Arithmetic

Pointers can be incremented or decremented to navigate through an array or block of memory.

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;

cout << *ptr; // Prints the first element (1)
ptr++;        // Moves to the next element
cout << *ptr; // Prints the second element (2)

 

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    for (size_t i = 0; i < 7; i++)
    {
        cout << *(arr + i) << endl;
    }
    return 0;
}

code prints the elements of an array using pointer arithmetic.

cout << *(arr + i) << endl;: Utilizes pointer arithmetic to access each element of the array. The expression arr + i calculates the memory address of the i-th element, and *(arr + i) dereferences the pointer to access the value stored at that address.

Output:
If you run this program, the output will be:

11
22
33
44
55
66
77

 

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    int *ptr;
    ptr = arr;
    for (size_t i = 0; i < 7; i++)
    {
        cout << *ptr << " ";
        ptr++;
    }
    return 0;
}

This code accomplishes the same goal as the previous example but uses a pointer (ptr) and pointer arithmetic to iterate through the array.

Output:
If you run this program, the output will be:

11 22 33 44 55 66 77

Passing Pointers to Functions

When passing an array to a function, you are actually passing a pointer to the first element of the array. This is due to the array decaying into a pointer in function arguments.

Example 3:

This code demonstrates the usage of pointers and a function that modifies the value it points to.

#include <iostream>
using namespace std;
int fun(int *p)
{
    *p = *p + 1;
    return *p;
}
int main()
{
    int x = 1;
    int *ptr = &x;
    cout << fun(ptr) << endl;
    cout << x << endl;
    cout << fun(&x) << endl;
    cout << x << endl;
    return 0;
}

Key points:

  1. Function fun:
    int fun(int *p): Takes a pointer to an integer as a parameter.
    *p = *p + 1;: Increments the value pointed to by the pointer.
    return *p;: Returns the updated value.
  2. Main Function:
    int x = 1;: Declares and initializes an integer variable x.
    int *ptr = &x;: Declares a pointer ptr and assigns the address of x to it.
    cout << fun(ptr) << endl;: Calls the function fun with the pointer ptr and prints the result. The value of x is now 2.
    cout << x << endl;: Prints the current value of x after the function call. It is now 2.
    cout << fun(&x) << endl;: Calls the function fun with the address of x directly and prints the result.
    The value of x is now 3.cout << x << endl;: Prints the final value of x. It is now 3.

Output:
If you run this program, the output will be:

2
2
3
3

 

Data Structures (struct)

In the world of programming, data structures play a pivotal role in how we organize and manipulate data efficiently. They act as the building blocks that enable us to create well-structured and organized programs. In this explanation, we will delve into one fundamental data structure in C++ known as struct.

What is a Data Structure?

Before we explore struct, let’s define what a data structure is. A data structure is a way of organizing and storing data in a computer’s memory to perform operations on that data more efficiently. It provides a blueprint for the storage and retrieval of information.

Introduction to struct in C++

struct in C++ is a user-defined data type that allows you to group together variables of different data types under a single name. Think of it as creating a custom data type tailored to the specific needs of your program. This makes your code more modular, organized, and easier to understand.

Syntax of struct:

The syntax for defining a struct is straightforward:

struct MyStruct

struct MyStruct

Example 1:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x;
    x.name = "Rolls-Royce";
    x.color = "Red";
    x.model = 2019;
    x.maxSpeed = 270;
    
    cout << x.name << endl;
    return 0;
}

code defines a struct named car that represents information about a car, and it creates an instance of this struct called x to store details about a specific car.

Key points:

  • Struct Definition (car):
    The struct named car has four member variables: name, color, maxSpeed, and model. These variables store information about a car.
  • Instance Creation (x):
    An instance of the car struct named x is created in the main function. This instance can store information about a specific car.
  • Assigning Values:
    Values are assigned to the member variables of the x instance using the dot (.) notation. For example, x.name = “Rolls-Royce” assigns the name “Rolls-Royce” to the name member variable.
  • Printing Information:
    The program prints the name of the car using cout << x.name << endl;. In this case, it will output “Rolls-Royce” to the console.

Output:
If you run this program, the output will be:

Rolls-Royce

Example 2:

Here is another way of initialization the values based on the previous example:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    cout << x.maxSpeed << endl;
    return 0;
}

Output:

250

Example 3:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = x;
    cout << y.name << endl;
    return 0;
}

Instance Creation and Initialization (x and y):

  • An instance of the car struct named x is created with initial values.
  • Another instance named y is created and initialized with the values of x. This is a memberwise copy, and each member of y gets the value of the corresponding member in x.

Example 4:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
}y;
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = {"Mercedes","Red",300,2016};
    if (x.maxSpeed > y.maxSpeed)
        cout << "car x is faster than car y";
    else
        cout << "car y is faster than car x";
    return 0;
}
  • Global Instance Declaration (y):
    An instance of the car struct named y is declared at the global scope. This means it can be accessed throughout the program.
  • Instance Creation and Initialization (x and Local y):
    – A local instance of the car struct named x is created with initial values.
    – Another local instance named y is created with different values. This y is local to the main function and shadows the global y within this scope.
  • Comparison and Output:
    The program compares the maximum speeds of cars x and y and prints a message indicating which car is faster.

Output:
If you run this program, the output will depend on the values assigned to maxSpeed in x and y. For the provided values, it will output:

car y is faster than car x

Pass ‘struct’ into function:

Example 5:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
void f(car f)
{
    cout << "Name = " << f.name << endl;
    cout << "Color = " << f.color << endl;
}
int main()
{
    car v = {"No name","Red",160,2000};
    f(v);
    return 0;
}

Key points:

  • Function Definition (f):
    The function f takes a car as a parameter and prints information about the car, specifically the name and color.
  • Instance Creation and Initialization (v):
    An instance of the car struct named v is created with initial values.
  • Function Call (f(v)):
    The program calls the function f with the v instance as an argument.

Output:
If you run this program, the output will be:

Name = No name
Color = Red

Example 6:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
car read_return(car&s)
{
    cout << "Enter car name:\n";
    cin >> s.name;
    cout << "Enter car color:\n";
    cin >> s.color;
    cout << "Enter car maximum speed:\n";
    cin >> s.maxSpeed;
    cout << "Enter car model:\n";
    cin >> s.model;
    return s;
}
int main()
{
    car v;
    read_return(v);
    car h;
    h = v;
    cout << h.name << endl;
    return 0;
}

Key points:

  • Function Definition (read_return):
    The function read_return takes a car reference as a parameter, reads input to populate its fields, and returns the modified car struct.
  • Function Call (read_return(v)):
    The program calls the function read_return with the v instance as a reference, allowing the function to modify the values of v.
  • Assignment and Printing:
    – The values of v are assigned to h.
    – The program prints the name of h.

Output:
If you run this program and enter values when prompted, the output will depend on the input provided. For example:

Enter car name:
BMW
Enter car color:
Blue
Enter car maximum speed:
250
Enter car model:
2022
BMW

Example 7:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car v = {"Kia"};
    v.fun(v);
    return 0;
}

Key points:

  • Member Function Definition (fun):
    The member function fun is defined inside the car struct.
    It takes a car as a parameter and prints its name.

Output:
If you run this program, the output will be:

Kia

Example 8:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car*h;
    car b = {"Toyota","Red",170,2008};
    h = &b;
    cout << h->color << endl;
    return 0;
}

Key points:

  • Pointer Declaration and Initialization (h):
    A pointer to a car named h is declared.
  • Instance Creation and Initialization (b):
    An instance of the car struct named b is created and initialized with specific values.
  • Pointer Assignment (h = &b):
    The address of b is assigned to the pointer h.
  • Pointer Dereferencing (h->color):
    The program prints the color of the car pointed to by h using the arrow operator (->).

Output:
If you run this program, the output will be:

Red

 

String

In C++, a string is a sequence of characters represented using the string class. Unlike C-style strings, which are arrays of characters, C++ strings are dynamic and provide a higher level of abstraction. The string class is part of the C++ Standard Template Library (STL), making it convenient and powerful for handling strings.

Declaring and Initializing Strings:

You can declare a string using the string keyword and initialize it in various ways:

// Declare and initialize strings
string str1 = "Hello, ";  // Initialization using a string literal
string str2("world!");    // Initialization using a constructor

// Concatenate strings
string result = str1 + str2;

When you use a string in C++, you must include its library this way:

#include <string>

Example:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string x = "Ahmad", y;
    y.assign(x);
    cout << "y = " << y << endl;

    return 0;
}

String Assignment:

  • string y;: Declares another string variable y.
  • y.assign(x);: Uses the assign method to copy the contents of string x to string y.

Output:

y = Ahmad

String Methods in C++:

Below is an explanation of various string methods in C++, along with their parameters and examples:

  1. at Method:
    Description: Returns the character at a specified position in the string.
    Parameters: Takes an index as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.at(0) << endl;
    
    // A
  2. length Method:
    Description: Returns the number of characters in the string.
    Parameters: No parameters.
    Example:

     string x = "Ahmad";
     cout << x.length() << endl;
    
     // 5
  3. size Method:
    Description: Same as length, returns the number of characters in the string.
    Parameters: No parameters.
    Example:

    string x = "Ahmad";
    cout << x.size() << endl;
    
    // 5
  4. substr Method:
    Description: Returns a substring of the original string.
    Parameters: Takes starting index and length as parameters.
    Example:

    string x = "Ahmad";
    cout << x.substr(1,3) << endl;
    
    // hma
  5. swap Method:
    Description: Swaps the content of two strings.
    Parameters: Takes another string as a parameter.
    Example:

    string x = "Ahmad", y = "Ali";
    cout << x.swap(y) << endl;
    
    // Swaps the content of x and y
  6. find Method:
    Description: Finds the first occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.find('a') << endl;
    
    // 3
  7. rfind Method:
    Description: Finds the last occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.rfind('a') << endl;
    
    // 3
  8. erase Method:
    Description: Erases characters from the string.
    Parameters: Takes starting index and count as parameters.
    Example:

    string x = "Ahmad";
    cout << x.erase(0,3) << endl;
    
    // ad
  9. replace Method:
    Description: Replaces a portion of the string with another string.
    Parameters: Takes starting index, length, and replacement string as parameters.
    Example:

    string x = "Ahmad";
    cout << x.replace(1,4,"li") << endl;
    
    // Ali
  10. insert Method:
    Description: Inserts characters into the string.
    Parameters: Takes starting index and string to insert as parameters.
    Example:

    string x = "Ahmad";
    cout << x.insert(5," Ali") << endl;
    
    // Ahmad Ali

These are some commonly used string methods in C++. Remember to include the <string> header for using these methods.

Introduction

C++ is a cross-platform programming language that can be used to create high-performance applications. It is a general-purpose language, which means it can be used to develop a wide variety of software, including operating systems, games, embedded systems, and more.

C++ is a popular choice for developing high-performance applications because it gives programmers a high level of control over system resources and memory. It is also a very efficient language, which means that C++ programs typically run faster than programs written in other languages.

C++ is a relatively complex language to learn, but it is also a very powerful language. Once you have mastered the basics of C++, you will be able to develop almost any type of software you can imagine.

Why is C++?

C++ is one of the most popular programming languages in the world for a reason. It is a powerful, versatile, and efficient language that can be used to create a wide variety of software.

Here are just a few of the reasons why C++ is so popular:

  • Performance: C++ programs are typically very fast and efficient. This is because C++ gives programmers a high level of control over system resources and memory.
  • Versatility: C++ can be used to develop a wide variety of software, from operating systems to games to embedded systems.
  • Portability: C++ programs can be compiled and run on a variety of platforms, including Windows, macOS, Linux, and more.
  • Community: C++ has a large and active community of developers. This means that there is a wealth of resources available to help you learn and use C++.

Difference between C and C++

C++ was developed as an extension of the C programming language. Both languages have a similar syntax, but C++ adds a number of new features, including:

  • Classes and objects: C++ supports classes and objects, which provide a way to encapsulate data and code into reusable units.
  • Templates: C++ templates allow you to create generic functions and classes that can be used with different data types.
  • Exception handling: C++ provides exception handling features that allow you to deal with errors in a structured way.

Get Started

If you are interested in learning C++, there are a number of resources available to help you get started. There are many good books and tutorials available online, and there are also a number of C++ communities where you can ask for help and advice.

Once you have learned the basics of C++, you can start developing your own applications. There are a number of different C++ compilers and development environments available, so you can choose the one that best suits your needs.

Conclusion

C++ is a powerful and versatile programming language that can be used to create a wide variety of software. It is a popular choice for developing high-performance applications, and it is also a good choice for beginners because it is relatively easy to learn.

else

The else statement in C++ is used to provide an alternate block of code to be executed if the condition of an if statement is false.

The general syntax of an else statement is as follows:

if (condition) {
  // code to execute if the condition is true
} else {
  // code to execute if the condition is false
}

For example, the following code uses an else statement to print a different message depending on whether the number variable is positive or negative:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is positive" << endl;
    else
        cout << "This number is negative" << endl;


    return 0;
}

Output should be one of the previous statements depending on the entered number. if the number is positive like 5, the output will be “This number is positive” and vice versa.

The else statement is a powerful tool for controlling the flow of your program. By using else statements, you can write more complex and efficient code.

Here are some general rules for using the if else statement:

  • The else statement must be used in conjunction with an if statement.
  • The else statement can be used to provide an alternate block of code to be executed if the condition of the if statement is false.
  • You can use nested if else statements to create more complex conditional statements:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int x = 0;
        cin >> x;
        if (x % 2 == 0)
            if (x > 50)
                cout << "it's Ok" << endl;
            else
                cout << "it's not Ok" << endl;
        else
            cout << "Odd" << endl;
    
    
        return 0;
    }
    

By understanding how to use the if else statement, you can write more efficient and reliable C++ code.

Getting Started

What is C++?

C++ is a general-purpose programming language that is used to create a wide range of applications, including operating systems, games, embedded systems, and web applications. C++ is known for its speed, efficiency, and flexibility.

Getting started with C++

To get started with C++, you will need to install a C++ compiler and IDE. A compiler is a program that converts C++ code into machine code that can be executed by a computer. An IDE is an integrated development environment that provides a variety of tools for writing, editing, compiling, and debugging C++ code.

Installing a C++ compiler and IDE

There are many different C++ compilers and IDEs available. For this tutorial, we will use Visual Studio for C++. Visual Studio is a free and powerful IDE that provides comprehensive support for C++ development.

To install Visual Studio for C++, visit the Visual Studio website and download the latest version.

Writing your first C++ program

Once you have installed Visual Studio for C++, you can start writing your first C++ program. To do this, create a new project and select the “C++ Console App” template.

Once you have created a new project, you can start writing C++ code in the main source file. The main source file is typically named main.cpp.

Here is a simple example of a C++ program:

C++
#include <iostream>
int main() {
  std::cout << "Hello, world!" << std::endl;
  return 0;
}

This program prints the message “Hello, world!” to the console.

Once you have written your C++ program, you can compile and run it by pressing F5.

Learning more about C++

Now that you have written your first C++ program, you can start learning more about the language. There are many resources available online and in libraries.

Here are a few tips for learning C++:

  • Start with the basics. Learn about variables, data types, operators, functions, and control flow statements.
  • Find a good tutorial or book. There are many resources available that can teach you the basics of C++.
  • Practice regularly. The best way to learn C++ is by writing code. Try to write simple programs at first, and gradually work your way up to more complex programs.
  • Use an IDE. An IDE can make it easier to write, edit, compile, and debug C++ code.

Conclusion

Getting started with C++ can be daunting, but it is also rewarding. C++ is a powerful and versatile language that can be used to create a wide range of applications.

By following the tips in this guide, you can start learning C++ today and start creating your own applications.

OOP in C++

Object-Oriented Programming (OOP) is an acronym that stands for the following concepts:

In procedural programming, the emphasis lies in writing procedures or functions designed to perform operations on data. In contrast, object-oriented programming revolves around the creation of objects that encapsulate both data and functions.

Object-oriented programming offers numerous advantages over procedural programming:

  1. OOP execution is typically faster and more straightforward.
  2. OOP provides a well-defined structure for organizing programs.
  3. OOP promotes the “Don’t Repeat Yourself” (DRY) principle in C++, reducing code duplication and enhancing code maintainability, modification, and debugging.
  4. OOP facilitates the development of highly reusable applications with reduced code volume and shorter development timelines.

As a helpful tip, adhering to the “Don’t Repeat Yourself” (DRY) principle involves identifying and extracting common code segments within an application, centralizing them for reuse rather than duplicating them throughout the codebase.

Review Function

The Structure of C++ program

#include <iostream>
using namespace std;

int main()
{
    cout << "Welcome to OOP in C++" << endl;

    return 0;
}

Let’s break down the structure and purpose of each command line in the provided C++ code:

#include <iostream>

Structure: This line begins with the #include preprocessor directive, followed by the <iostream> header file enclosed in angle brackets.

Purpose: This line includes the Input/Output Stream Library (iostream), which is essential for performing input and output operations in C++. It provides functionalities like cin for input and cout for output.

using namespace std;

Structure: The using namespace std; line declares that the code will be using the std namespace.

Purpose: The std namespace contains the standard C++ library components, including the cout and endl used in the code. By including this line, you can use these components without explicitly specifying the namespace each time you use them.

int main()
{

Structure: This line marks the beginning of the main function, which is the entry point of every C++ program.

Purpose: The main function is where the program execution starts. It is required in every C++ program, and the code within the curly braces {} defines the body of the main function.

cout << "Welcome to OOP in C++" << endl;

Structure: This line uses the cout object to output the text “Welcome to OOP in C++” to the console. The << operator is used for streaming the text to the output.

Purpose: This line is responsible for displaying a welcome message on the console, indicating that the program is focused on Object-Oriented Programming (OOP) in C++.

    return 0;
}

Structure: The return 0; line signifies the end of the main function. The 0 is returned to the operating system, indicating that the program executed successfully.

Purpose: The return 0; line is a common way to indicate a successful termination of the program. The value 0 is typically returned to the operating system to signify that the program executed without errors.

Libraries in C++

In C++, a library is a collection of pre-compiled functions, classes, and procedures that can be used by a program. These libraries provide a set of functionalities that can be utilized to perform common tasks, ranging from basic input/output operations to complex mathematical computations. Libraries offer a way to modularize code, promote code reuse, and streamline development by providing ready-made solutions for various tasks.

Here are some key aspects of libraries in C++:

  1. Standard Template Library (STL):
    The C++ Standard Library, often referred to as the Standard Template Library (STL), is a core part of C++. It includes a wide range of generic algorithms (e.g., sorting, searching) and data structures (e.g., vectors, lists, maps) that are implemented using templates. The STL simplifies programming by providing efficient and generic solutions to common problems.
  2. Header Files:
    C++ libraries are typically distributed as header files (with the extension .h or .hpp) and implementation files (with the extension .cpp). Header files contain declarations of functions, classes, and other entities that can be used in your program, while the implementation files contain the actual code.
  3. IOStream Library:
    The iostream library is a fundamental part of the C++ Standard Library and provides functionality for input and output operations. It includes cin (for input) and cout (for output), among other stream classes. Here’s an example of using the iostream library:

    #include <iostream>
    
    int main() {
        std::cout << "Hello, C++!" << std::endl;
        return 0;
    }
    
  4. Math Library:
    The cmath library provides a set of mathematical functions, such as trigonometric, logarithmic, and exponential functions.
  5. User-Defined Libraries:
    Apart from the standard libraries, you can create your own libraries to encapsulate and organize your code. This involves creating header files that declare the functions and classes, and implementation files that define their behavior. You can then include your custom library in other C++ programs.

Function in C++

In the realm of programming, functions play a pivotal role in organizing code, enhancing reusability, and promoting a structured approach to problem-solving. In C++, a function is a self-contained unit of code designed to perform a specific task or achieve a particular objective. It encapsulates a set of instructions, allowing you to break down a complex program into smaller, more manageable pieces.

Key Concepts
1. Modularity:
Functions enable the decomposition of a program into smaller, more manageable modules. Each function handles a specific aspect of the overall functionality, promoting a modular and organized code structure.

2. Reusability:
Once a function is defined, it can be reused in different parts of the program or even in other programs. This promotes the “Don’t Repeat Yourself” (DRY) principle, saving both time and effort.

3. Abstraction:
Functions provide a level of abstraction, allowing you to focus on high-level functionality without getting bogged down by the implementation details. This abstraction enhances code readability and simplifies the debugging process.

4. Parameters and Return Values:
Functions can accept input parameters and return values, allowing for dynamic and interactive code. Parameters provide a way to pass information into a function, while return values allow functions to communicate results back to the calling code.

Basic Syntax
A typical C++ function follows this basic syntax:

returnType functionName(parameterType1 parameterName1, parameterType2 parameterName2, ...) {
    // Function body: Code to perform the desired task
    // Optionally, a return statement to provide a result back to the caller
}

Let’s break down the components:

returnType: Specifies the type of data the function will return (if any).
functionName: The unique identifier for the function.
parameters: Input values that the function receives.
functionBody: The set of instructions defining the function’s behavior.

Example 1:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    return x + y;
}

int main()
{
    cout << sum(10,20) << endl;
    return 0;
}

This C++ code is a simple program that calculates and displays the sum of two numbers.

  • Define a Sum Function:
int sum(int x, int y)
{
    return x + y;
}

This block of code creates a function called sum. It takes in two numbers (x and y) and gives back their sum.

  • Use the Sum Function in the Main Part:
int main()
{
    cout << sum(10, 20) << endl;
    return 0;
}

Here, the main part is like the director of the program. It says, “Hey, calculate the sum of 10 and 20 using the sum function, and show me the result on the screen.” The endl is like pressing Enter on the keyboard; it moves to the next line.

  • Run the Program:

When you run this program, it does the calculation (10 + 20) inside the sum function, then displays the result (30) on the screen. The return 0; part tells the computer that everything went well.

 

Of course, the user can enter the data to be calculated using cin, using this command:

cin >> x >> y;

This command can be located inside the main function, but it’s better to use it inside the function itself to have a cleaner code.
See the following example:

#include <iostream>

using namespace std;
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;

    return 0;
}

This code asks the user to input two numbers, adds them together, and then displays the result.

  • Define a Sum Function:
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}

This block of code defines a function called sum. It asks the user to enter two numbers, reads those numbers from the keyboard (cin), and then returns the sum of those numbers.

  • Use the Sum Function in the Main Part:
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;
    return 0;
}

In the main part, it starts with x and y set to 0. It then calls the sum function, passing x and y as arguments. The sum function gets user input, adds the numbers, and returns the result. The result is stored in z. Finally, it displays the sum with a message using cout.

So, in a nutshell, this program is like a simple interactive calculator. It asks you for two numbers, adds them together, and then shows you the result on the screen.

Providing initial values to variables is crucial to avoid errors.

Example 2:

#include <iostream>
using namespace std;

double avg(double m1, double m2, double m3)
{
    return (m1 + m2 + m3) / 3;
}

int main()
{
    cout << avg(100, 60, 50);
    return 0;
}

This code calculates and displays the average of three numbers.

The avg function takes in three numbers (m1, m2, and m3), adds them together, divides by 3, and returns the result. This is how you calculate the average of three numbers.
In the main part, it directly calls the avg function with three numbers (100, 60, and 50) as arguments. It then uses cout to display the result, which is the average of these three numbers.

Example 3:

#include <iostream>
using namespace std;

int max(int n1, int n2, int n3)
{
    int m = n1;
    if (m < n2)
        m = n2;
    if (m < n3)
        m = n3;
    return m;
}

int main()
{
    cout << max(100, 20, 800);
    return 0;
}

This code finds and displays the maximum of three numbers.

The max function takes in three numbers (n1, n2, and n3) and uses conditional statements (if) to determine the maximum among them. It begins by considering n1 as the initial maximum value and then employs conditional statements (if) to compare it with the other values. Whenever the condition is met, the maximum value is updated. The maximum value is then returned.

In the main part, it directly calls the max function with three numbers (100, 20, and 800) as arguments. It then uses cout to display the result, which is the maximum of these three numbers.

We can find a minimum value among other values using the same logic but changing the conditions.

Example 4:

#include <iostream>
using namespace std;

void p()
{
    cout << "myName\n";
}

int main()
{
    p();
    return 0;
}

This code defines a function and then calls that function in the main part of the program.

The function called p used void keyword before the function name which means that this function doesn’t return any value. Inside the function, it uses cout to display the text “myName” on the screen.

In the main part, it calls the p function. When a function is called, the program jumps to that function, performs the tasks inside it, and then returns to where it was called. In this case, it jumps to the p function, prints “myName” to the screen, and then returns to the main function.

  • Now, let’s talk about the concept of a void function:

A void function is a function that doesn’t return a value. In this example, the p function is a void function because it has the void keyword before its name.

Void functions are useful when you want a function to perform a task or set of tasks without needing to provide a result back to the part of the program that called it.

Example 5:

#include <iostream>
using namespace std;

int mul(int x = 10, int y = 50)
{
    return x*y;
}

int main()
{
    cout << mul(10) << endl;
    cout << mul(10, 2) << endl;
    cout << mul() << endl;

    return 0;
}

This code demonstrates the use of default arguments in a function.

The function called mul multiplies two numbers (x and y). The interesting part is that both x and y have default values assigned (10 and 50, respectively). If these values are not provided when the function is called, these defaults will be used.

In the main part, it calls the mul function multiple times with different combinations of arguments:

mul(10): It uses the default value 50 for y, so it multiplies 10 by 50.
mul(10, 2): It uses both 10 and 2 provided as arguments, so it multiplies 10 by 2.
mul(): Since no arguments are provided, it uses both default values (10 and 50), so it multiplies 10 by 50.

  • Now, let’s talk about the concept of default arguments:

Default arguments allow you to provide values to parameters in a function declaration, so if the caller doesn’t provide values, the default values are used.

In this example, the mul function has default values for both x and y, making it flexible when calling the function with different numbers of arguments.

Example 6:

#include <iostream>
using namespace std;

void ref(int &x, int &y)
{
    x += 1;
    y += 1;
}

int main()
{
    int p = 0, t = 0;
    ref(p, t);
    cout << "p = " << p << endl;
    cout << "t = " << t << endl;
    return 0;
}

This code demonstrates the concept of “call by reference.”

The function called ref has an interesting part which is that it takes references (&x and &y) as parameters, indicating that it will directly modify the values of the variables passed to it.

In the main part, it declares two variables (p and t) and initializes them to 0. Then, it calls the ref function with p and t as arguments. Inside the ref function, both p and t are increased by 1. Finally, it prints the values of p and t after the function call using cout.

  • Now, let’s talk about the concept of call by reference:

In C++, when you pass parameters to a function by reference (using &), the function receives the memory addresses of the actual variables, not just copies of their values.

This means any changes made to the parameters inside the function directly affect the original variables outside the function.

In this example, the ref function modifies the values of p and t directly because they are passed by reference.

Built-in functions

Built-in functions in C++ are pre-defined functions provided by the C++ programming language. These functions are part of the standard C++ library and offer ready-made solutions for common tasks. They are designed to perform specific operations and can be used by programmers without the need to write the entire code for those operations.

Here’s a simple breakdown:

  • Ready-made Tools:
    Built-in functions are like tools that are already available for you to use. Instead of creating these tools from scratch, you can simply use the built-in functions to perform various tasks.
  • Part of the Standard C++ Library:
    These functions are part of the standard C++ library, which is a collection of tools and functionalities that come with every C++ compiler. You don’t need to create or install anything extra to use them.
  • Common Operations:
    Built-in functions are designed to perform common operations such as input/output, mathematical calculations, string manipulations, and more. Examples include cout and cin for printing and reading from the console, sqrt for square root, and strlen for getting the length of a string.
  • Saves Coding Time:
    By using built-in functions, you can save a lot of time and effort. You don’t need to write complex code for tasks that are already handled by these functions.
  • Consistency Across Platforms:
    Since these functions are part of the standard library, they provide a consistent way to perform operations across different platforms and compilers. This makes your code more portable and ensures it works similarly on various systems.

In essence, built-in functions in C++ are like a toolbox that comes with the language. They provide a set of tools you can use to make your programming tasks easier, faster, and more standardized. As you become more familiar with C++, you’ll discover and leverage these functions to streamline your code.

Here are some common built-in functions in C++:

  1. Input/Output Functions:
    cout: Used to display output to the console.
    cin: Used to take input from the user through the console.
  2. Mathematical Functions:
    sqrt(): Calculates the square root of a number.
    abs(): Returns the absolute value of a number.
    pow(): Raises a number to a specified power.
  3. String Functions:
    strlen(): Returns the length of a string.
    strcpy(): Copies one string to another.
    strcat(): Concatenates (joins) two strings.
  4. Character Functions:
    isalpha(): Checks if a character is an alphabet letter.
    isdigit(): Checks if a character is a digit.
    toupper(): Converts a character to uppercase.
  5. Array Functions:
    sizeof(): Returns the size of a data type or an array.
    sort(): Sorts elements in an array in ascending order.
  6. Memory Functions:
    malloc(): Allocates a specified amount of memory dynamically.
    free(): Releases memory that was previously allocated with malloc.
  7. Time and Date Functions:
    time(): Returns the current time in seconds.
    ctime(): Converts a time value into a string representation.

Example 7:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    cout << abs(-10) << endl;
    cout << max(10, 20) << endl;
    cout << max(max(10, 20), 30) << endl;
    int x = 10, y = 20;
    swap(x,y);
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    
    return 0;
}

This code demonstrates the usage of several built-in functions from the <cmath> and <algorithm> libraries.

  • abs(-10): Calculates the absolute value of -10 and prints the result (10) to the console.
  • max(10, 20): Finds the maximum of two numbers (10 and 20) and prints the result (20) to the console.
  • max(max(10, 20), 30): Compares three numbers (10, 20, and 30) and finds the maximum among them. It prints the result (30) to the console.
  • swap(x, y): Swaps the values of x and y. After this line, x will be 20, and y will be 10.

Output:

10
20
30
x = 20
y = 10

 

 

Review Arrays

What is an Array?

An array is a fundamental data structure in C++ that allows you to store multiple elements of the same data type under a single name. These elements can be accessed using an index, making arrays a powerful tool for handling collections of data efficiently.

Declaration and Initialization:

In C++, declaring an array involves specifying the data type of its elements and the array’s name. Initialization can be done during declaration or later using assignment statements. Let’s take a look at the syntax:

// Declaration
int myArray[5];

// Initialization during declaration
int anotherArray[] = {1, 2, 3, 4, 5};

// Accessing elements
cout << anotherArray[2]; // Output: 3

Array Indexing:
Array indexing starts from 0, meaning the first element is accessed using index 0, the second with index 1, and so on. Be cautious not to access elements beyond the array’s bounds, as it can lead to undefined behavior.

Manipulating Arrays:
Iterating Through an Array:
Looping through an array is a common operation. You can use a for loop to access each element:

for (int i = 0; i < 5; ++i) {
    cout << myArray[i] << " ";
}

Array Size:
Determining the size of an array is crucial for avoiding index out-of-bounds errors. You can use the sizeof operator or calculate the size using the number of elements and data type size:

int size = sizeof(anotherArray) / sizeof(anotherArray[0]);

Example 1:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }
    
    for (int i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }

    return 0;
}

This program takes input for an array of integers and then prints the entered values.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }

    for (int i = 0; i < 7; i++)
    {
        cout << "index" << i << " = " << arr[i];
        cout << endl;
    }
    cout << endl;

    return 0;
}

This program is a simple console application that takes input for an array of 7 integers from the user and then displays each element along with its index.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    char g[5];
    cin.get(g, 5);
    cout << g << endl;

    return 0;
}

This program demonstrates reading a character array from user input using cin.get().

char g[5];
This line declares a character array named g that can hold 5 characters.

cin.get(g, 5);
This line uses cin.get() to read up to 4 characters (since the array size is 5, one space is reserved for the null terminator \0) from the user and stores them in the character array g. It stops reading when it encounters a newline character, the end of the stream, or when the specified number of characters have been read.

In summary, this program prompts the user to enter up to 4 characters (excluding the null terminator) and then prints the entered characters using cout.

The null terminator

Often represented by the character \0 (backslash followed by zero), is a special character used in C and C++ to denote the end of a string. It is essential for string manipulation functions to determine where a string ends in memory.

In memory, a string is represented as an array of characters. The null terminator is placed at the end of this array to indicate the boundary of the string. When a program processes a string, it can keep reading characters until it encounters the null terminator, signifying the end of the string data.

For example:

const char myString[] = "Hello";

In memory, this would be stored as follows:

H   e   l   l   o   \0

Here, the null terminator \0 follows the characters of the string, indicating the end of the string. Functions that operate on strings, like those in the C Standard Library or C++ Standard Library, use the null terminator to determine the length of the string and to recognize the end of the string when performing operations.

Example 4:

#include <iostream>
using namespace std;

int main()
{
    char g1[10];
    char g2[10];
    cin.getline(g1, 10);
    cin.getline(g2, 10);
    
    cout << g1 << endl;
    cout << g2 << endl;

    return 0;
}

This program demonstrates the use of the cin.getline() function to read input lines into character arrays and then prints them.

char g1[10];
char g2[10];

These lines declare two character arrays, g1 and g2, each capable of holding up to 9 characters plus the null terminator \0.

cin.getline(g1, 10);
cin.getline(g2, 10);

These lines use cin.getline() to read lines of input from the user into the character arrays g1 and g2. The function takes two arguments: the array to store the input (g1 or g2) and the maximum number of characters to read (9 in this case, leaving one space for the null terminator). The getline function reads characters until it encounters a newline character (‘\n’) or reaches the specified limit.

In summary, this program allows the user to input two lines of text, each up to 9 characters long, and then prints the entered lines. The use of cin.getline() ensures that the input is read as a line, and the program avoids potential issues with the input buffer.

Example 5:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char a1[] = "A";
    char a2[] = "B";
    cout << strcmp(a1, a2);

    return 0;
}

This C++ program compares two strings using the strcmp function from the C Standard Library.

This code includes the necessary header files for input/output operations (iostream) and string-related functions (cstring). The cstring header is included for the strcmp function.

char a1[] = "A";
char a2[] = "B";

These lines declare and initialize two character arrays, a1 and a2. Each array contains a single character and is automatically null-terminated by the compiler. Remember that a string in C/C++ is essentially an array of characters terminated by the null character (‘\0’).

cout << strcmp(a1, a2);

This line uses the strcmp function to compare the strings stored in a1 and a2. The result is printed to the console. The strcmp function returns an integer value:

  • If the strings are equal, it returns 0.
  • If a1 is lexicographically less than a2, it returns a negative value.
  • If a1 is lexicographically greater than a2, it returns a positive value.

The result of the comparison is printed to the console. This will be either 0 if the strings are equal, a negative value if a1 is less than a2, or a positive value if a1 is greater than a2.

 

Multi-dimensional Arrays:
C++ supports multi-dimensional arrays, which can be thought of as arrays of arrays. A 2D array, for example, can be declared and accessed like this:

int matrix[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

Additional Tips:
Passing Arrays to Functions:
When passing an array to a function, you need to use pointers. Here’s a quick example:

void printArray(int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
}

Standard Template Library (STL) Arrays:
For more advanced functionalities, consider using the array class from the C++ Standard Template Library (STL). It provides additional features and safety checks.

#include <array>

std::array<int, 5> stlArray = {1, 2, 3, 4, 5};

Example 6:

#include <iostream>
#include <cstring>
using namespace std;

void search(int arr[], int s, int k)
{
    bool g = false;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] == k)
            g = true;
    }
    if (g)
        cout << "Found\n";
    else
        cout << "Not Found\n";
}

int main()
{
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    search(arr, 7, 55);
    

    return 0;
}

This program defines a function called search that searches for a specific value in an integer array. The main function then calls this search function to check if a particular value is present in the given array.

The function called search takes three parameters: arr (an integer array), s (the size of the array), and k (the value to search for).
It initializes a boolean variable g to false, which will be used to track whether the value k is found in the array.
The function then iterates through the array using a for loop. If the current element is equal to the target value k, it sets g to true.
After the loop, it checks the value of g and prints either “Found” or “Not Found” based on whether the target value was found in the array.

The main function initializes an integer array arr with values.
It then calls the search function, passing the array arr, the size of the array (7), and the value to search for (55).

Depending on whether the value 55 is found in the array, the program will output either “Found” or “Not Found.”

Example 7:

#include <iostream>
using namespace std;

void sort(int arr[], int s)
{
    int t;
    for (size_t i = 0; i < s - 1; i++)
    {
        for (size_t j = 0; j < s - 1; j++)
        {
            if (arr[j] > arr[j+1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
}

int main()
{
    int t;
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    sort(arr, 7);
    for (size_t i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }
    return 0;
}

This program implements a simple sorting algorithm known as the Bubble Sort.

The sort function implements the Bubble Sort algorithm for sorting an array of integers.
It takes two parameters: arr (the integer array to be sorted) and s (the size of the array).
The function uses nested for loops to iterate through the array. The inner loop compares adjacent elements and swaps them if they are in the wrong order, pushing the larger element towards the end of the array.
The process repeats until the entire array is sorted in ascending order.

The main function initializes an integer array arr with values.
It then calls the sort function, passing the array arr and its size (7), which sorts the array using the Bubble Sort algorithm.
Finally, the sorted array is printed using a for loop.

The program will output the sorted array: 0 1 7 22 55 88 99

Conclusion:
Mastering arrays in C++ is a crucial step in becoming a proficient programmer. They serve as the building blocks for more complex data structures and algorithms. If you’ve found this review helpful, don’t forget to check out our video tutorials on [Adel Nasim] for hands-on examples and practical insights.

Classes

What is a Class?

In C++, a class is a user-defined data type that encapsulates data and the functions that operate on that data. It serves as a blueprint for creating objects, which are instances of the class. Imagine a class as a template that defines the structure and behavior of objects.

To declare a class in C++, you use the class keyword.

Once a class is defined, you can create objects of that class. Objects are instances of the class, each with its own set of data.

In C++, classes support access modifiers like public, private, and protected. These modifiers control the visibility and accessibility of class members.

Example 1:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

class car{
    private: 
        char name[15];
        char color[10];
        int maxSpeed;
        int model;
    public:
        void setName(char n[])
        {
            strcpy_s(name, n);
        }
        void setColor(char n[])
        {
            strcpy_s(color, n);
        }
        void setMaxSpeed(int m)
        {
            maxSpeed = m;
        }
        void setModel(int m)
        {
            model = m;
        }
        char* getName()
        {
            return name;
        }
        char* getColor()
        {
            return color;
        }
        int getMaxSpeed()
        {
            return maxSpeed;
        }
        int getModel()
        {
            return model;
        }
        void print()
        {
            cout << "name = " << name << "\n"
            << "color = " << color << "\n"
            << "maxspeed = " << maxSpeed << "\n"
            << "model = " << model << "\n";
        }
};
int main()
{
    car x;
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);
    x.print();
    return 0;
}

This C++ code defines a simple class named car that represents information about a car, such as its name, color, maximum speed, and model. The program creates an instance of this class, sets its attributes, and prints the details using member functions. Let’s break down the code step by step:

  • Class Definition: car
class car {
private: 
    char name[15];
    char color[10];
    int maxSpeed;
    int model;
public:
    // Member functions for setting attributes
    void setName(char n[]) { strcpy_s(name, n); }
    void setColor(char n[]) { strcpy_s(color, n); }
    void setMaxSpeed(int m) { maxSpeed = m; }
    void setModel(int m) { model = m; }

    // Member functions for retrieving attributes
    char* getName() { return name; }
    char* getColor() { return color; }
    int getMaxSpeed() { return maxSpeed; }
    int getModel() { return model; }

    // Member function to print details
    void print() {
        cout << "name = " << name << "\n"
             << "color = " << color << "\n"
             << "maxspeed = " << maxSpeed << "\n"
             << "model = " << model << "\n";
    }
};

– Private Members: The class has private member variables (name, color, maxSpeed, and model), which can only be accessed within the class.

– Public Members: The class provides public member functions (setName, setColor, setMaxSpeed, etc.) to set and retrieve the values of these private variables.

  • main Function:
int main() {
    car x;

    // Setting attributes of the car
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);

    // Printing the details using the print() member function
    x.print();

    return 0;
}

– Object Creation: An object x of type car is created.

– Setting Attributes: The attributes of the car (name, color, maxSpeed, and model) are set using the member functions (setName, setColor, setMaxSpeed, and setModel).

– Printing Details: The details of the car are printed using the print member function, which displays the values of the car’s attributes.

The output of this program would be:

name = kia
color = red
maxspeed = 300
model = 2017

This demonstrates a simple usage of a class in C++, encapsulating data and behavior related to a car. The class provides methods to set and retrieve attributes, promoting encapsulation and data hiding. This is a fundamental concept in object-oriented programming.

Example 2:

#include <iostream>
using namespace std;

class triangle{
    private: 
        float base;
        float height;
    public:
        void setBase_height(float b, float h)
        {
            base = b;
            height = h;
        }
        float area()
        {
            return 0.5 * base * height;
        }
        void print()
        {
            cout << "base = " << base << endl
            << "height = " << height << endl
            << "area = " << area() << endl;
        }
};
int main()
{
    triangle ob;
    ob.setBase_height(5, 10);
    ob.print();
    return 0;
}

This code defines a class named triangle that represents a triangle. The class has private member variables for the base and height of the triangle, and it provides member functions for setting these values, calculating the area, and printing the details of the triangle. Let’s break down the code step by step:

  • Class Definition: triangle
class triangle {
private: 
    float base;
    float height;

public:
    // Member function to set base and height
    void setBase_height(float b, float h) {
        base = b;
        height = h;
    }

    // Member function to calculate the area of the triangle
    float area() {
        return 0.5 * base * height;
    }

    // Member function to print details of the triangle
    void print() {
        cout << "base = " << base << endl
             << "height = " << height << endl
             << "area = " << area() << endl;
    }
};

– Private Members: The class has private member variables base and height, which can only be accessed within the class.

– Public Members: The class provides public member functions (setBase_height, area, and print) to set the base and height, calculate the area, and print the details of the triangle.

  • main Function:
int main() {
    triangle ob;

    // Setting base and height of the triangle
    ob.setBase_height(5, 10);

    // Printing the details of the triangle
    ob.print();

    return 0;
}

– Object Creation: An object ob of type triangle is created.

– Setting Base and Height: The setBase_height member function is called to set the base to 5 and height to 10 for the triangle.

– Printing Details: The print member function is called to print the details of the triangle, including the base, height, and calculated area.

The output of this program would be:

base = 5
height = 10
area = 25

This demonstrates a basic usage of a class in C++ to represent and manipulate data related to a triangle. The class encapsulates the data and behavior related to the triangle, promoting encapsulation and making the code more organized and reusable. The program calculates and displays the area of the triangle using the provided member functions.

Constructors

What is a Constructor?
In C++, a constructor is a special member function within a class that is automatically invoked when an object of that class is created. Its primary purpose is to initialize the object’s data members or perform any necessary setup for the object. Constructors ensure that the object starts with a valid state.

  1. Constructor Name:
    Constructors have the same name as the class they belong to.
  2. No Return Value:
    Constructors do not return any value, not even void.
  3. Object Initialization:
    Constructors are used to initialize and set up a new object when it is created.

Types of Constructors:

  1. Default/ Empty Constructor:
    Automatically generated by the compiler if no constructor is explicitly defined.
    Initializes object members with default values.
    Syntax: ClassName() { /* Initialization code */ }
    Example 1:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height =h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob;
        ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }

    An empty constructor is defined (Triangle()). It is automatically called when an object is created and prints “first constructor.”

  2. Parameterized Constructor:
    Accepts parameters during object creation to customize the initial state.
    Provides flexibility for objects to start with different values.
    Syntax: ClassName(type param1, type param2, …) { /* Initialization code */ }
    Example 2:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
                base = 0;
                height = 0;
            }
            //parameterized constructor
            Triangle(int b, int h)
            {
                base = b;
                height = h;
                cout << "parameterized constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height = h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob(5, 10);
        //ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }
    

    Parameterized Constructor:

    Accepts parameters (int b and int h) for custom initialization.
    Prints “parameterized constructor” when called.
    The parameterized constructor is employed during object creation, providing initial values for the base and height members.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;
class student {
    private:
        char name[20];
        int id;
    public:
        student()
        {
            strcpy_s(name, "no name");
            id = 0;
        }
        student(char n[], int i)
        {
            cout << "parameterized constructor\n";
            strcpy_s(name, n);
            id = i;
        }
        student(char n[])
        {
            strcpy_s(name, n);
        }
        void print()
        {
            cout << "name = " << name << endl;
            cout << "id = " << id << endl;
        }
};
int main()
{
    student ob("Mohammed", 1450902032);
    ob.print();

    return 0;
}

This code defines a class student representing a student with private member variables name and id. The class includes three constructors: an empty constructor, a parameterized constructor with both name and id, and a parameterized constructor with only the name. Let’s break down the code step by step:

– Class Definition: student

class student {
private:
    char name[20];
    int id;

public:
    // Empty Constructor
    student() {
        strcpy_s(name, "no name");
        id = 0;
    }

    // Parameterized Constructor (with name and id)
    student(char n[], int i) {
        cout << "parameterized constructor\n";
        strcpy_s(name, n);
        id = i;
    }

    // Parameterized Constructor (with name only)
    student(char n[]) {
        strcpy_s(name, n);
    }

    // Member Function to print student details
    void print() {
        cout << "name = " << name << endl;
        cout << "id = " << id << endl;
    }
};
  • Empty Constructor:
    Initializes name to “no name” and id to 0.
  • Parameterized Constructor (with name and id):
    Accepts parameters (char n[] and int i).
    Prints “parameterized constructor” when called.
    Sets name and id based on the provided values.
  • Parameterized Constructor (with name only):
    Accepts a parameter (char n[]).
    Initializes only the name attribute.
  • Member Function:
    print: Displays the student’s name and id.

– main Function:

int main() {
    // Object of class student created using the parameterized constructor with name and id
    student ob("Mohammed", 1450902032);

    // Printing the details of the student
    ob.print();

    return 0;
}
  • Object Creation:
    An object ob of type student is created using the parameterized constructor with both name and id.
  • Printing Details:
    The print member function is called to display the details of the student, including the name and id.

The output of this program would be:

parameterized constructor
name = Mohammed
id = 1450902032

This code illustrates the use of multiple constructors in a C++ class. Depending on the provided arguments during object creation, different constructors can be called to initialize the object accordingly.

3. Copy Constructor:

Example 4:

#include <iostream>
using namespace std;
class Copy {
    private:
        int a1, a2, a3, a4, a5, a6, a7, a8;
    public:
        Copy(int aa1, int aa2, int aa3, int aa4,
            int aa5, int aa6, int aa7, int aa8)
        {
            a1 = aa1;
            a2 = aa2;
            a3 = aa3;
            a4 = aa4;
            a5 = aa5;
            a6 = aa6;
            a7 = aa7;
            a8 = aa8;
        }
        Copy(const Copy &a)
        {
            a1 = a.a1;
            a2 = a.a2;
            a3 = a.a3;
            a4 = a.a4;
            a5 = a.a5;
            a6 = a.a6;
            a7 = a.a7;
            a8 = a.a8;
        }
        void print()
        {
            cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
                 << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
        }
};
int main()
{
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    g.print();
    Copy h(g);
    h.print();

    return 0;
}

This code defines a class Copy with two constructors – one for initializing an object with specific values and another for performing a deep copy of an existing object. Let’s break down the code:

– Class Definition: Copy

class Copy {
private:
    int a1, a2, a3, a4, a5, a6, a7, a8;

public:
    // Parameterized Constructor for Initialization
    Copy(int aa1, int aa2, int aa3, int aa4,
         int aa5, int aa6, int aa7, int aa8) {
        a1 = aa1;
        a2 = aa2;
        a3 = aa3;
        a4 = aa4;
        a5 = aa5;
        a6 = aa6;
        a7 = aa7;
        a8 = aa8;
    }

    // Copy Constructor for Deep Copy
    Copy(const Copy &a) {
        a1 = a.a1;
        a2 = a.a2;
        a3 = a.a3;
        a4 = a.a4;
        a5 = a.a5;
        a6 = a.a6;
        a7 = a.a7;
        a8 = a.a8;
    }

    // Member Function to Print Object Details
    void print() {
        cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
             << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
    }
};
  • Parameterized Constructor:
    Initializes the object with specific values provided as arguments.
  • Copy Constructor:
    Performs a deep copy of an existing object (Copy &a).
    Copies each member variable of the source object to the new object.
  • Print Function:
    Displays the values of the object’s member variables.

– main Function:

int main() {
    // Creating an object 'g' and initializing it with specific values
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    
    // Printing the details of object 'g'
    g.print();

    // Creating another object 'h' and initializing it by performing a deep copy of 'g'
    Copy h(g);

    // Printing the details of object 'h'
    h.print();

    return 0;
}
  • Object Creation (g):
    An object g of type Copy is created and initialized with specific values.
  • Printing Details (g):
    The print member function is called to display the details of object g.
  • Object Creation (h):
    Another object h is created and initialized by performing a deep copy of object g using the copy constructor.
  • Printing Details (h):
    The print member function is called to display the details of object h

The output of this program would be:

1 2 3 4 5 6 7 8 
1 2 3 4 5 6 7 8 

This code illustrates the usage of a copy constructor to create a new object with the same values as an existing object, ensuring a deep copy of the data.

Destructor

What is a Destructor?

In C++, a destructor is a special member function that is automatically called when an object goes out of scope or is explicitly deleted. Its primary purpose is to clean up resources or perform actions before the object’s memory is deallocated.

Destructor Charachteristics:

  1. Name and Syntax:
    Name: Destructors have the same name as the class, preceded by a tilde (~).
    Syntax: ~ClassName()
  2. Automatic Invocation:
    Destructors are automatically invoked when an object goes out of scope or is explicitly deleted.
    They handle the cleanup and deallocation of resources held by the object.
  3. No Return Type or Parameters:
    Destructors don’t have a return type, not even void.
    They do not accept any parameters.
  4. Single Destructor per Class:
    Each class can have only one destructor.
    It’s responsible for cleaning up resources allocated during the object’s lifetime.
  5. Manual Deletion:
    For objects created dynamically using new, the destructor is called explicitly using delete.
    This is essential for releasing memory allocated on the heap.
  6. Resource Cleanup:
    Destructors are often used to release resources such as dynamic memory, file handles, database connections, etc.
    Ensures proper cleanup before the object is destroyed.

Why Use Destructors?

Destructors are essential for proper resource management and maintaining the integrity of your program. They are particularly useful when dealing with dynamic memory allocation, file handling, or any situation where cleanup is necessary.

Syntax of a Destructor:

The syntax for a destructor is straightforward. It has the same name as the class preceded by a tilde (~). Here’s an example:

class MyClass {
public:
    // Constructor
    MyClass() {
        // Constructor code
    }

    // Destructor
    ~MyClass() {
        // Destructor code
    }
};

Example 1:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(int a, int b)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}

This code defines a class Rectangle representing a rectangle with private member variables W (width) and H (height). The class includes a constructor for creating a rectangle and a destructor for cleaning up resources when the rectangle is deleted. Let’s break down the code:

– Class Definition: Rectangle

class Rectangle {
private:
    int W, H;

public:
    // Constructor
    Rectangle(int a, int b) {
        W = a;
        H = b;
        cout << "A rectangle has been created\n";
    }

    // Destructor
    ~Rectangle() {
        cout << W << " " << H << " A rectangle has been deleted\n";
    }
};
  • Constructor:
    Initializes the W (width) and H (height) member variables with the values passed as arguments.
    Prints a message indicating that a rectangle has been created.
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

– main Function:

int main() {
    // Creating two objects of class Rectangle
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}
  • Object Creation:
    Two objects, R1 and R2, of type Rectangle are created in the main function.
  • Constructor Execution:
    The constructor of the Rectangle class is executed for each object, initializing their width and height.
    Messages are printed indicating that rectangles have been created.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for R1 and R2 are automatically called.
    Messages are printed indicating that rectangles have been deleted, along with their dimensions.

The output of this program would be:

A rectangle has been created
A rectangle has been created
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

This output demonstrates the automatic invocation of the constructor when objects are created and the destructor when objects go out of scope (at the end of the program in this case). The destructor prints messages indicating the deletion of rectangles along with their dimensions.

Example 2:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(): W(0), H(0)
        {
            cout << "W = " << W << " H = " << H << endl;
        }
        Rectangle(int a, int b): W(0), H(0)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
            Rectangle ob;
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);
    Rectangle R3;

    return 0;
}
  • Default Constructor:
    Initializes W and H to 0.
    Prints the initial values of W and H when an object is created with this constructor.
  • Parameterized Constructor:
    Accepts parameters a and b to set the dimensions of the rectangle.
    Initializes W and H to 0 before assigning the provided values.
    Prints a message indicating that a rectangle has been created.
    Creates another object ob inside the constructor (not recommended in general practice).
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

The output of this program would be:

A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
W = 0 H = 0
0 0 A rectangle has been deleted
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

Example 3:

#include <iostream>
using namespace std;
class phone {
    private:
        char name[10];
        char model[10];
        int price;
    public:
        phone() {}
        phone(char n[], char m[], int p)
        {
            strcpy(name, n);
            strcpy(model, m);
            price = p;
        }
        void print();
        ~phone();
};
phone::~phone()
{
    cout << "object destructed\n"
}
void phone::print()
{
    cout << "Name = " << name << endl;
    cout << "Model = " << model << endl;
    cout << "Price = " << price << endl;
}
int main()
{
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();
    return 0;
}

This code defines a class phone representing a phone with private member variables name, model, and price. The class includes a default constructor, a parameterized constructor, a member function (print), and a destructor. Let’s break down the code:

– Class Definition: phone

class phone {
private:
    char name[10];
    char model[10];
    int price;

public:
    // Default Constructor
    phone() {}

    // Parameterized Constructor
    phone(char n[], char m[], int p) {
        strcpy(name, n);
        strcpy(model, m);
        price = p;
    }

    // Member Function to Print Phone Details
    void print();

    // Destructor
    ~phone();
};
  • Default Constructor:
    An empty default constructor is provided.
  • Parameterized Constructor:
    Accepts parameters n (name), m (model), and p (price) to initialize the object’s member variables.
  • Member Function (print):
    Displays the details of the phone, including its name, model, and price.
  • Destructor:
    Outputs a message when an object of the class is destructed.

– Destructor Implementation:

phone::~phone() {
    cout << "object destructed\n";
}

The destructor is defined outside the class and prints a message when an object of the class is destructed.

– main Function:

int main() {
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();

    return 0;
}
  • Object Creation:
    Two objects, ob1 and ob2, of type phone are created.
    ob2 is initialized using the parameterized constructor.
  • Printing Details:
    The print member function is called for ob2 to display its details.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for ob1 and ob2 are automatically called.
    A message is printed indicating that an object has been destructed.

The output of this program would be:

Name = HUAWI
Model = MATE 9
Price = 400
object destructed

This output demonstrates the creation, printing, and destruction of phone objects, including the use of the parameterized constructor and the destructor.

Example 4:

#include <iostream>
#include <cstring>
using namespace std;
class Student {
    private:
        char name[20];
        int ID;
    public:
        Student()
        {
            cout << "Object created\n";
        }
        ~Student()
        {
            cout << "Object destructed\n";
        }
        void Set_Name_ID(char n[], int id)
        {
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
}; //end of class definition
void F(Student S)
{
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
int main()
{
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Funcrion\n";
    St1.print();
    return 0;
}

This code defines a class Student representing a student with private member variables name and ID. The class includes a default constructor, a destructor, a member function to set the name and ID, and another member function to print the student’s details. Additionally, there is a function F that takes a Student object as a parameter and demonstrates object creation, assignment, modification, and destruction within a function. Let’s break down the code:

– Class Definition: Student

class Student {
private:
    char name[20];
    int ID;

public:
    // Default Constructor
    Student() {
        cout << "Object created\n";
    }

    // Destructor
    ~Student() {
        cout << "Object destructed\n";
    }

    // Member Function to Set Name and ID
    void Set_Name_ID(char n[], int id) {
        strcpy(name, n);
        ID = id;
    }

    // Member Function to Print Student Details
    void print(void) {
        cout << name << "\t" << ID << endl;
    }
};
  • Default Constructor:
    Prints a message indicating that an object has been created.
  • Destructor:
    Prints a message indicating that an object has been destructed.
  • Set_Name_ID Function:
    Accepts parameters n (name) and id (ID) to set the member variables.
  • print Function:
    Prints the name and ID of the student.

– Function F:

void F(Student S) {
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
  • Creates a Student object S1 within the function.
  • Copies the content of the parameter S into S1.
  • Modifies the content of S using the Set_Name_ID function.
  • Prints the details of both S and S1.

– main Function:

int main() {
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Function\n";
    St1.print();
    return 0;
}
  • Object Creation and Modification:
    Creates two Student objects, St1 and St2.
    Sets their names and IDs using the Set_Name_ID function.
  • Function Call:
    Calls the function F passing St1 as a parameter.
  • Object Destruction:
    Prints messages indicating the destruction of objects when they go out of scope (end of the function or program).

The output of this program would be:

Object created
Object created
Going to Function
Object created
Sami    12345
Ahmad   11111
Object destructed
Object destructed
Back from Funcrion
Ahmad   11111
Object destructed
Object destructed

This output demonstrates the creation, modification, and destruction of Student objects, including the behavior of the default constructor and destructor. The F function illustrates object copying and modification within a function.

Structure

Structures in C++ provide a powerful way to organize and store related data under a single name. They are a fundamental concept in Object-Oriented Programming (OOP) that allows you to create custom data types to suit your program’s needs. In this guide, we’ll delve into the basics of structures in C++.

What is a Structure?

A structure is a user-defined data type in C++ that enables you to group together different data types under a single name. This makes it easier to manage and organize related information. Unlike primitive data types, structures can hold a collection of variables with various data types.

Defining a Structure:

To create a structure, you use the struct keyword, followed by the structure’s name and a block of variables inside curly braces. Here’s a simple example:

// Define a structure named 'Person'
struct Person {
    char name[50];
    int age;
    float height;
};

In this example, we’ve created a structure named Person with three members: a character array for the name, an integer for age, and a float for height.

Accessing Structure Members:

You can access the members of a structure using the dot (.) operator.

Example 1:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
};

int main()
{
    car g;
    g.name = "Kia";
    g.color = "red";
    cout << g.name << endl; //Kia
    cout << g.color << endl;  //red

    return 0;
}

This code defines a simple program that utilizes a structure named car. The structure car has four members: name (string), color (string), maxspeed (integer), and model (integer). The program then declares a variable g of type car and assigns values to its name and color members. Finally, it prints the values of name and color to the console.

Initializing Structure Variables:

You can initialize structure variables at the time of declaration, similar to how you initialize primitive variables:

// Initialize structure variables
Person person3 = {"Alice", 30, 5.5};

Example 2:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
}g, k;

int main()
{
    k = {"aa", "black", 300, 97};
    g = {"kia", "red", 250, 96};
    cout << g.maxspeed << endl;

    return 0;
}

This code defines a structure named car with four members (name, color, maxspeed, and model). Additionally, it declares two structure variables, g and k, of type car. In the main function, it assigns values to these structure variables using an initialization syntax and then prints the value of the maxspeed member of the g structure variable. Here’s a detailed explanation:

– Structure Definition and Variable Declaration:

struct car {
    string name;
    string color;
    int maxspeed;
    int model;
} g, k;  // Declaration of structure variables g and k of type car

Defines a structure named car and declares two structure variables g and k of type car.

– Main Function:

int main() {
    // Initialization of structure variable k
    k = {"aa", "black", 300, 97};

    // Initialization of structure variable g
    g = {"kia", "red", 250, 96};

    // Print the value of the maxspeed member of the g structure variable
    cout << g.maxspeed << endl;

    return 0;
}

Execution Flow:

  1. Initialization of Variables:
    k = {“aa”, “black”, 300, 97}; initializes the members of structure variable k with the provided values.
    g = {“kia”, “red”, 250, 96}; initializes the members of structure variable g with the provided values.
  2. Print to Console:
    cout << g.maxspeed << endl; prints the value of the maxspeed member of the g structure variable to the console, followed by a newline.
  3. Return Statement:
    return 0; indicates that the program has executed successfully.

The output of this program would be:

250

Functions and Structures:

Structures can be passed as arguments to functions, allowing you to create more modular and organized code.

Example 3:

#include <iostream>
#include <string>
using namespace std;

struct Distance
{
    int feet;
    float inches;
};
Distance add_distance(Distance d1, Distance d2)
{
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

int main()
{
    Distance x, y, z;
    cout << "Enter feet value \n";
    cin >> x.feet >> y.feet;
    cout << "Enter inches value \n";
    cin >> x.inches >> y.inches;
    z = add_distance(x, y);
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

This code demonstrates the use of structures to represent distances in feet and inches. It defines a structure Distance with two members: feet (integer) and inches (float). The program then includes a function add_distance to add two distance structures, and the main function takes user input for two distances, adds them using the add_distance function, and prints the result. Here’s a step-by-step explanation:

– Structure Definition:

struct Distance {
    int feet;
    float inches;
};

Defines a structure named Distance with two members: feet (integer) and inches (float).

– Function to Add Distances:

Distance add_distance(Distance d1, Distance d2) {
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

Defines a function add_distance that takes two Distance structures as parameters, adds their corresponding feet and inches members, and returns a new Distance structure representing the sum.

– Main Function:

int main() {
    Distance x, y, z;

    // User input for the first distance (x)
    cout << "Enter feet value \n";
    cin >> x.feet;
    cout << "Enter inches value \n";
    cin >> x.inches;

    // User input for the second distance (y)
    cout << "Enter feet value \n";
    cin >> y.feet;
    cout << "Enter inches value \n";
    cin >> y.inches;

    // Add the two distances using the add_distance function
    z = add_distance(x, y);

    // Print the result
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

Execution Flow:

  1. User Input:
    The user is prompted to enter the feet and inches values for two distances (x and y).
  2. Function Call:
    The add_distance function is called with the x and y structures as arguments, and the result is stored in the z structure.
  3. Print to Console:
    The program prints the result, displaying the summed feet and inches of the distances.
  4. Return Statement:
    return 0; indicates that the program has executed successfully.

– Sample Execution:
If the user enters:

Enter feet value
3
Enter inches value
6.5
Enter feet value
2
Enter inches value
3.2

The program would output:

z.feet = 5 z.inches = 9.7

Example 4:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;

struct exam
{
    float first;
    float second;
    float final;
};
class subject
{
        char name[10];
        exam Exam;
    public:
        subject()
        {
            strcpy(name, "no name");
            Exam = {0, 0, 0};
        }
        subject(char n[], float fa, float s, float fi)
        {
            strcpy(name, n);
            Exam = {fa, s, fi};
        }
        float total()
        {
            return Exam.first + Exam.second + Exam.final;
        }
        void print()
        {
            cout << "The subject = " << name << endl
                 << "First Exam = " << Exam.first << endl
                 << "Second Exam = " << Exam.second << endl
                 << "Final Exam = " << Exam.final << endl
                 << "The Total is = " << total() << endl;
        }
};

int main()
{
    subject e("OOP", 25, 24, 49);
    e.print();
    return 0;
}

This code defines a program that uses a combination of structures and classes to model a subject with exam scores. Let’s break down the code step by step:

– Structure Definition:

struct exam {
    float first;
    float second;
    float final;
};

Defines a structure named exam with three members representing exam scores: first, second, and final.

– Class Definition:

class subject {
    char name[10];
    exam Exam;
public:
    // Default constructor
    subject() {
        strcpy(name, "no name");
        Exam = {0, 0, 0};
    }

    // Parameterized constructor
    subject(char n[], float fa, float s, float fi) {
        strcpy(name, n);
        Exam = {fa, s, fi};
    }

    // Member function to calculate the total exam score
    float total() {
        return Exam.first + Exam.second + Exam.final;
    }

    // Member function to print subject details
    void print() {
        cout << "The subject = " << name << endl
             << "First Exam = " << Exam.first << endl
             << "Second Exam = " << Exam.second << endl
             << "Final Exam = " << Exam.final << endl
             << "The Total is = " << total() << endl;
    }
};

Defines a class named subject with private members:

  • name: An array of characters representing the subject’s name.
  • Exam: An instance of the exam structure representing exam scores.

The class includes:

  • A default constructor (subject()) initializing name to “no name” and Exam to all zeros.
  • A parameterized constructor (subject(char n[], float fa, float s, float fi)) initializing name and Exam with provided values.
  • A total() member function calculating the total exam score.
  • A print() member function printing subject details.

– Main Function:

int main() {
    // Create an instance of the subject class
    subject e("OOP", 25, 24, 49);

    // Call the print() member function to display subject details
    e.print();

    return 0;
}

In the main function:

  • An instance e of the subject class is created using the parameterized constructor.
  • The print() member function is called on the e object, displaying the details of the subject and its exam scores.

– Sample Output:

The subject = OOP
First Exam = 25
Second Exam = 24
Final Exam = 49
The Total is = 98

This output represents the details of the “OOP” subject, including scores on the first, second, and final exams, as well as the total score.

 

New Delete

In object-oriented programming (OOP) with C++, pointers play a crucial role in managing memory and accessing objects dynamically. Here’s a brief explanation of pointers in the context of OOP in C++:

Definition:

A pointer is a variable that holds the memory address of another variable. In C++, pointers can be used to store addresses of objects created dynamically on the heap.

Example 1:

int main()
{
    int var1 = 11;
    int var2 = 22;
    cout << &var1 << endl;
    cout << &var2 << endl;
    
    int *ptr;
    ptr = &var2;
    *ptr = 5000;
    cout << *ptr << endl;
    cout << var2 << endl;
}

This code demonstrates the use of pointers to manipulate variables and access their memory addresses.

  1. Variable Declaration and Initialization:
    int var1 = 11;
    int var2 = 22;
    

    Two integer variables, var1 and var2, are declared and initialized with values 11 and 22, respectively.

  2. Printing Memory Addresses:
    cout << &var1 << endl;
    cout << &var2 << endl;
    

    The memory addresses of var1 and var2 are printed using the address-of operator (&). This reveals the locations in memory where these variables are stored.

  3. Pointer Declaration and Assignment:
    int *ptr;
    ptr = &var2;
    

    A pointer variable ptr of type int is declared. The address of var2 is assigned to the pointer ptr.

  4. Using Pointer to Modify Variable:
    *ptr = 5000;
    

    The value pointed to by ptr is changed to 5000. Since ptr points to the address of var2, this also modifies the value of var2.

  5. Printing Pointer Value and Modified Variable:
    cout << *ptr << endl;
    cout << var2 << endl;
    

    The value pointed to by ptr (5000) and the modified value of var2 are printed. Both values should be the same, as the pointer was used to modify the content of var2.

The output of the code might look like this:

0x7fff5fbff628  // Memory address of var1
0x7fff5fbff624  // Memory address of var2
5000             // Value pointed to by ptr
5000             // Modified value of var2

The exact memory addresses and values may vary depending on the system and compiler.

Dynamic Memory Allocation:

OOP often involves the creation of objects using the new operator for dynamic memory allocation. Pointers are used to store the address of the dynamically allocated objects.

Deleting Dynamic Objects:

When dynamic objects are no longer needed, they should be explicitly deleted to avoid memory leaks. The delete operator is used.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int *p;
    p = new int;
    *p = 10;
    cout << p << endl;
    delete p;
}

This code demonstrates dynamic memory allocation and deallocation for an integer variable. Here’s an explanation of the code:

#include <iostream>
using namespace std;

int main()
{
    // Declare a pointer variable
    int *p;

    // Allocate memory for an integer on the heap
    p = new int;

    // Assign a value to the dynamically allocated integer
    *p = 10;

    // Print the address of the dynamically allocated memory
    cout << p << endl;

    // Deallocate the dynamically allocated memory
    delete p;

    return 0;
}

Explanation:

  1. Pointer Declaration:
    int *p;
    

    Declares a pointer variable p that will be used to store the address of a dynamically allocated integer.

  2. Dynamic Memory Allocation:
    p = new int;
    

    Allocates memory on the heap to store an integer and assigns the address of the allocated memory to the pointer p.

  3. Assigning a Value:
    *p = 10;
    

    Dereferences the pointer p and assigns the value 10 to the dynamically allocated integer.

  4. Printing the Address:
    cout << p << endl;
    

    Prints the address of the dynamically allocated memory. This address is on the heap and may vary each time the program runs.

  5. Memory Deallocation:
    delete p;
    

    Deallocates the memory previously allocated with new. This step is crucial to prevent memory leaks.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    // Declare two pointer variables
    int *p1, *p2;

    // Allocate memory for the first integer on the heap
    p1 = new int;
    *p1 = 10;

    // Print the location of the pointer and the content of the allocated memory
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    // Allocate memory for the second integer on the heap
    p2 = new int;
    *p2 = 10;

    // Print the location of the second pointer and the content of the allocated memory
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;

    // Deallocate the dynamically allocated memory
    delete p1;
    delete p2;

    return 0;
}

This code demonstrates dynamic memory allocation for two integer variables using pointers. Here’s an explanation of the code:

  1. Pointer Declaration:
    int *p1, *p2;
    

    Declares two pointer variables, p1 and p2, which will be used to store the addresses of dynamically allocated integers.

  2. Dynamic Memory Allocation (p1):
    p1 = new int;
    *p1 = 10;
    

    Allocates memory on the heap for an integer using new, assigns the address to p1, and assigns the value 10 to the dynamically allocated integer.

  3. Printing Information (p1):
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    Prints the location of the pointer variable p1 and the content of the memory it points to.

  4. Dynamic Memory Allocation (p2):
    p2 = new int;
    *p2 = 10;
    

    Allocates memory on the heap for another integer using new, assigns the address to p2, and assigns the value 10 to the dynamically allocated integer.

  5. Printing Information (p2):
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;
    

    Prints the location of the pointer variable p2 and the content of the memory it points to.

  6. Memory Deallocation:
    delete p1;
    delete p2;
    

    Deallocates the dynamically allocated memory using delete to avoid memory leaks.

Example 4:

#include <iostream>
using namespace std;

class CRectangle 
{
        int *width, *height;
    public:
        CRectangle(int, int); //constructor
        ~CRectangle(); //destructor
        int area()
        {
            return (*width * *height);
        }
};
CRectangle::CRectangle(int a, int b)
{
    width = new int;
    height = new int;
    *width = a;
    *height = b;
}
CRectangle::~CRectangle()
{
    delete width;
    delete height;
}
int main()
{
    CRectangle rect(3, 4), rectb(5, 6);
    cout << "rect area: " << rect.area() << endl;
    cout << "rectb area: " << rectb.area() << endl;
    return 0;
}

This code defines a class CRectangle for rectangles using dynamic memory allocation for width and height. Here’s a breakdown of the code:

  1. Class Definition (CRectangle):
    The class CRectangle represents rectangles, with private members width and height stored as dynamic integer pointers.
  2. Constructor (CRectangle::CRectangle):
    The constructor allocates memory for width and height using new and initializes them with the provided values.
  3. Destructor (CRectangle::~CRectangle):
    The destructor deallocates the memory for width and height using delete.
  4. Member Function (area):
    The area function calculates and returns the area of the rectangle using the values stored in width and height.
  5. Main Function:
    Creates instances of CRectangle (rect and rectb) with dynamic memory allocation for width and height.
    Calls the area function to calculate and display the area of each rectangle.
    The destructors are automatically called when the instances (rect and rectb) go out of scope, freeing the dynamically allocated memory.

 

 

Array of object and Pointers to Objects

In the world of object-oriented programming (OOP) with C++, managing multiple objects efficiently is crucial. Two powerful concepts that help achieve this are Arrays of Objects and Pointers to Objects. This documentation will provide a clear understanding of both concepts and how they can be employed in C++.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};

    // Printing the memory address of the array (address of the first element)
    cout << arr << endl;

    // Printing the value at the first element of the array
    cout << *arr << endl;

    // Printing the memory address of the second element of the array
    cout << arr + 1 << endl;

    // Printing the memory address of the last element of the array
    cout << arr + 4 << endl;

    // Printing the value at the last element of the array
    cout << *(arr + 4) << endl;
    
    // Using a loop to print all elements of the array using pointer arithmetic
    for (size_t i = 0; i < 5; i++)
    {
        cout<< *(arr + i) << endl;
    }

    return 0;
}

This program demonstrates the use of pointers with arrays.

The output will display the memory addresses, values, and elements of the array based on the pointer arithmetic and loop iterations.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};
    int *p;
    p = arr;
    for (size_t i = 0; i < 5; i++)
    {
        cout << *p << endl;
        p++;
    }

    return 0;
}

This C++ program demonstrates the use of a pointer to iterate through an array.

The output will display the values of each element in the array, printed one at a time, as the pointer p is incremented within the loop.

10
50
40
77
33

Note:

  • The pointer p is initially set to the address of the first element of the array.
  • Incrementing the pointer (p++) makes it point to the next element in the array.
  • This approach provides an alternative way to iterate through array elements using pointers.

Example 3:

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Student
{
        char name[20];
        int ID;
    public:
        Student() //empty constructor
        {
            cout << "empty\n";
            strcpy(name, "No name");
            ID = 0;
        }
        Student(char n[], int id) //constructor overloading
        {
            cout << "parameterize\n";
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
};
int main()
{
    Student S1("Ali", 123), S2("Ahmad", 456);
    Student arr[3];
    for (int i = 0; i < 3; i++)
        arr[i].print();
    return 0;
}

This program demonstrates the use of constructor overloading and default constructors in a class Student. Let’s break down the code:

  1. Class Student:
    Defines a class named Student with private data members name and ID.
    Contains two constructors: an empty constructor and a parameterized constructor.
    Provides a member function print() to display student details.
  2. Empty Constructor:
    Student()
    {
        cout << "empty\n";
        strcpy(name, "No name");
        ID = 0;
    }
    

    Initializes name with “No name” and ID with 0.
    Prints “empty” when an object is created using this constructor.

  3. Constructor Overloading:
    Student(char n[], int id)
    {
        cout << "parameterize\n";
        strcpy(name, n);
        ID = id;
    }
    

    Initializes name and ID with the provided arguments.
    Prints “parameterize” when an object is created using this constructor.

  4. print() Function:
    void print(void)
    {
        cout << name << "\t" << ID << endl;
    }
    
    

    Prints the student’s name and ID.

  5. Creating Objects:
    Objects S1 and S2 are created using the parameterized constructor, displaying “parameterize” for each object.
    An array arr of Student objects is created using the default constructor, displaying “empty” for each object.
  6. Printing Student Details:
    The print() function is called for each object in the array to display their details.

Output:
The output will display the constructor messages and the details of each student in the array.

 

 

 

Enumeration

Introduction

In C++, an enumeration, also known as enumerated type, is a user-defined data type that consists of a set of named integer constants. These constants are essentially representative names assigned to integer values.

Declaration:

  • The enum keyword is used to declare an enumeration.
  • You list the constant names separated by commas, optionally enclosed in curly braces.
  • By default, constants start with a value of 0 and increment by 1 for each subsequent one.
  • You can explicitly assign specific integer values to individual constants.

Example 1:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
enum days {sat = 1, sun, mon, tue, wed, thu, fri};
int main()
{
    string d[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
    days m[7] = {sat, sun, mon, tue, wed, thu, fri};
    for (size_t i = 0; i < 7; i++)
    {
        cout << m[i] << " - " << d[i] << endl;
    }
    return 0;
}

Enumeration days:

  • Declares an enumeration named days to represent the days of the week.
  • Assigns values to each day: sat = 1, sun, mon, etc. (subsequent days get implicit values incremented from the previous one).

String Array d:

  • Creates an array of strings named d with a size of 7, holding the full day names (“sat”, “sun”, …, “fri”).

Enumeration Array m:

  • Creates an array of enumeration values named m with a size of 7, containing the day enumerations (sat, sun, …, fri).

for Loop:

  • Iterates through the elements of both d and m using a single index i.
  • For each iteration:
    – Prints the current enumeration value from m[i] followed by a hyphen (“-“).
    – Prints the corresponding day name from d[i] on the same line.

Example 2:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
string da[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
enum Days {sat = 1, sun, mon, tue, wed, thu, fri};
class week {
        Days d[7];
    public:
        void setday(Days w[])
        {
            for (size_t i = 0; i < 7; i++)
                d[i] = w[i];
        }
        void p()
        {
            for (size_t i = 0; i < 7; i++)
                cout << "The number of day " <<  da[i] << " = " << d[i] << endl;
        }
};
int main()
{
    Days d[7] = {sat, sun, mon, tue, wed, thu, fri};
    week g;
    g.setday(d);
    g.p();
    return 0;
}

Array da:

  • Declares a global string array da of size 7, storing the full day names (“sat”, “sun”, …, “fri”).

Enumeration Days:

  • Defines an enumeration named Days to represent the days of the week with integer values:
    – sat = 1
    – sun (implicitly 2)
    – mon (implicitly 3)
    – …
    – fri (implicitly 7)

Class week:

  • Represents a “week” concept.
    – Member variable:
    * d is an array of Days enumeration type, holding the numerical day values for a week (e.g., sat, sun, …).
    – Member methods:
    * setday(Days w[]): Takes an array of Days enumeration values as input and assigns them to the d member array, copying the day values into the object.
    * p(): Prints the day names and their corresponding numerical values from the d array. It iterates through the array, accessing both the current da string and the d value at the same index to print the pair.

main Function:

  • Creates an array d of Days type and initializes it with sat, sun, …, fri.
  • Instantiates a week object named g.
  • Calls the setday method of g to pass the d array (containing the day values) to the object.
  • Calls the p method of g, which prints the day information in the format “The number of day <day name> = <day value>”.

The code demonstrates the use of enumerations and classes to represent and manage day-of-the-week information in C++.

Static Class Member Static Member Function

Introduction

In C++, “static class members” and “static member functions” introduce class-level elements that are not associated with individual objects of the class.

#include <iostream>
#include <string>
using namespace std;
void f()
{
    static int x = 0;
    x++;
    cout << x << endl;
}
int main()
{
    f();
    f();
    return 0;
}

This C++ program defines a function f() that increments a static integer variable x each time it is called, and then prints the value of x to the standard output. The main() function calls f() twice.

Here’s what the program does:

  • The function f() is defined. It contains a static variable x initialized to 0.
  • Each time f() is called, it increments x by 1 and prints the new value of x.
  • In the main() function, f() is called twice.
  • When f() is called the first time, x is incremented from 0 to 1, and 1 is printed.
  • When f() is called the second time, x is incremented from 1 to 2, and 2 is printed.

Therefore, when you run the program, it should output:

1
2

Here’s what static does in this context:

  1. Preserves Value between Function Calls: When a variable is declared as static inside a function, its value persists between function calls. This means that the variable retains its value even after the function f() exits. In the example, the variable x retains its value between calls to f().
  2. Initialization: Static variables are initialized only once, at the start of the program execution. In this case, the static variable x is initialized to 0 the first time the function f() is called. Subsequent calls to f() do not reinitialize x.
  3. Storage Duration: Static variables have “static storage duration,” meaning they are allocated memory for the entire duration of the program’s execution. This memory is allocated in the data segment of the program.
  4. Scope: The scope of a static variable declared inside a function is limited to that function. It cannot be accessed from outside the function. In this example, x can only be accessed within the f() function.

Static Class Member

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
//define how many objects are created 
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            cout << "Numbers of students constructed: " << count << endl;
        }
}; //end of class
int Student::count = 0;
int main()
{
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

Class Definition (Student):

  • It defines a class Student with private data members name, first, second, final, total, and ID.
  • The count variable is declared as static within the class. This means it is shared among all instances of the Student class, and its value persists across multiple Student objects.

Constructor:

  • The class has a default constructor Student() which initializes the data members with default values.
  • In the constructor, the name is set to “No name”, ID is set to 0, and exam scores are set to 0.
  • Each time a Student object is constructed, the count variable is incremented, and the total number of constructed students is printed.

Static Member Initialization:

  • The count static member is initialized outside the class definition.

Main Function:

  • In the main() function, two Student objects (S1 and S2) are created using the default constructor. The program prints the number of students constructed after each object creation.
  • Then, an array St of three Student objects is created. Again, the program prints the number of students constructed after creating this array.

Output:

Construct 2 objects
Numbers of students constructed: 1
Numbers of students constructed: 2

Construct 3 objects
Numbers of students constructed: 3
Numbers of students constructed: 4
Numbers of students constructed: 5

The count static member variable is used to keep track of the total number of Student objects that have been created. Each time a Student object is constructed (i.e., when the constructor is called), the count is incremented. This allows the program to keep track of how many Student objects have been instantiated across the entire program execution.

Static Member Function

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        static void print_count()
        {
            cout << "Students constructed: " << count << endl;
        }
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            print_count();
        }
}; //end of class
int Student::count = 0;
int main()
{
    Student::print_count();
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

In this updated version of the program, a static member function print_count() has been added to the Student class. Here’s what the static keyword does in this context:

  • Static Member Function: The member function print_count() is declared as static. This means that it belongs to the class itself, rather than to individual instances (objects) of the class. Static member functions do not have access to non-static member variables or functions directly because they are not associated with any particular object.
  • Accessing Static Member Variables: Inside the static member function print_count(), the static member variable count is accessed directly. Since count is also static, it can be accessed without needing an instance of the class.
  • Accessing Static Member Function: Static member functions can be called using the class name followed by the scope resolution operator (::). For example, Student::print_count() calls the print_count() function of the Student class.
  • Usage: In the main() function, Student::print_count() is called before any Student objects are created. This demonstrates that static member functions can be called without the need for object instantiation.
  • Initialization and Increment: Inside the Student constructor, the count variable is incremented each time a new Student object is constructed. The print_count() function is called within the constructor to display the updated count after each object creation.

This program demonstrates the usage of a static member function to access a static member variable and provide functionality associated with the class itself, rather than individual objects of the class.

Constant Object Constant Member Function

Introduction

In C++, a constant variable is a variable whose value cannot be changed once it has been initialized. The value remains constant throughout the execution of the program. Constant variables are declared using the const keyword.

Constant Object

  • Declaration: A constant object is declared by using the const keyword along with the object’s type.
  • Immutable: Once declared as const, the member variables of the object cannot be changed.
  • Calling Member Functions: A constant object can only call constant member functions of its class. This prevents any operations that might modify the object’s internal state.

Constant Member Function

  • Declaration: A member function is declared as constant by appending the const keyword to its declaration and definition.
  • Promise Not to Modify: A constant member function implicitly promises not to modify any of the non-static data members of its class.
  • Enforce Correctness: This helps the compiler enforce correctness and prevents unintentional side effects.

Example

#include <iostream>
using namespace std;
class time {
    private:
        int h, m, s;
    public:
        void print() const //constant function
        {
            cout << "Time = " << h << ":" << m << s << endl;
        }
        time(int i, int j, int k)
        {
            h = i;
            m = j;
            s = k;
        }
};
int main()
{
    const time noon(12, 0, 0); //constant object
    noon.print();

    return 0;
}

In the provided code, both constant functions and constant objects play important roles:

Constant Function (print() const):

  • The member function print() is declared as const, making it a constant member function.
  • A constant member function ensures that it does not modify the state of the object it is called on. It promises not to modify any non-static member variables of the class.
  • In this code, the print() function is responsible for displaying the time stored in the time object. Since it does not modify the object’s state, it is declared as const.
  • By declaring print() as a constant member function, it allows constant objects to call this function.

Constant Object (const time noon(12, 0, 0)):

  • An object named noon of the class time is created and declared as const. This makes noon a constant object.
  • A constant object is an object whose state cannot be modified after initialization. Any attempt to modify its state will result in a compilation error.
  • In this code, the noon object represents a specific time, 12:00:00, and it cannot be changed once created.
  • Constant objects are useful when you want to ensure that the object’s state remains unchanged throughout its lifetime, providing guarantees of immutability and safety.
  • By declaring noon as a constant object, it ensures that the print() function, which is also marked as const, can be called on it. This allows the print() function to access the noon object’s state without fear of modification.

In summary, the constant function (print() const) ensures that it does not modify the object’s state, and the constant object (const time noon(12, 0, 0)) guarantees that its state remains unchanged throughout its lifetime. These concepts work together to enforce immutability and safety in the code.

Friend Function/Friend class

In C++, a friend function or friend class is a feature that allows a function or a class to access private and protected members of another class. This feature breaks encapsulation to some extent but can be useful in specific scenarios where tight coupling between classes is necessary or when implementing certain design patterns.

Friend Function:

A friend function is a regular function that is granted access to private and protected members of a class. To declare a function as a friend of a class, you need to declare it within the class declaration preceded by the friend keyword.

Example 1:

#include <iostream>
using namespace std;
class myClass {
        int a, b;
    public:
        myClass(int i, int j)
        {
            a = i;
            b = j;
        }
        friend int sum(myClass ob);
};
int sum(myClass ob)
{
    return ob.a + ob.b;
}
int main()
{
    myClass o(10, 20);
    cout << sum(o) << endl;
    return 0;
}

In this C++ code snippet, a class called myClass is defined with two private integer members a and b. The class also has a constructor to initialize these members. Additionally, There is a declared friend function sum inside the class.

The sum function takes an object of type myClass as its argument and returns the sum of the private members a and b of that object.

In the main function, There is an object o of type myClass with initial values of 10 and 20, and then a call to the sum function passing this object o as an argument. Finally, the output of the result of the sum function using cout.

Here’s the breakdown of the code execution:

  1. An object o of type myClass is created with values 10 and 20.
  2. The sum function is called with the object o as an argument.
  3. Inside the sum function, the private members a and b of the object ob are accessed due to the friend declaration, and their sum is returned.
  4. The returned sum is then printed using cout.

So, when you run this program, it should output:

30

Example 2:

#include <iostream>
using namespace std;
class CRectangle {
    private:
        int width, height;
        friend CRectangle duplicate(CRectangle);
    public:
        void set_values(int, int);
        int area(void)
        {
            return (width * height);
        }
};
void CRectangle::set_values(int a, int b)
{
    width = a;
    height = b;
}
CRectangle duplicate(CRectangle R)
{
    CRectangle T;
    T.width = R.width * 2;
    T.height = R.height * 2;
    return T;
}
int main()
{
    CRectangle rect, rectb;
    rect.set_values(2, 3);
    cout << "The area before duplicate = " << rect.area() << endl;
    rectb = duplicate(rect);
    cout << "The area after duplicate = " << rectb.area() << endl;
    return 0;
}

This C++ code defines a class CRectangle representing a rectangle. The class has private data members width and height, and two member functions set_values and area.

In the private section, width and height are the dimensions of the rectangle. The set_values function is used to set the values of width and height. The area function calculates and returns the area of the rectangle.

The duplicate function is declared as a friend of CRectangle. This means it has access to the private members of CRectangle.

The set_values function sets the width and height of the rectangle based on the provided parameters.

The duplicate function takes a CRectangle object as a parameter, creates a new CRectangle object T, and assigns T’s width and height to be twice that of the input R’s width and height. It then returns the new rectangle T.

In the main function:

  1. CRectangle objects rect and rectb are created.
  2. rect’s set_values function is called to set its dimensions to 2×3.
  3. The area of rect before duplication is printed.
  4. duplicate function is called with rect as an argument, and the returned rectangle is assigned to rectb.
  5. The area of rectb after duplication is printed.

The output of this program will be:

The area before duplicate = 6
The area after duplicate = 24

Example 3:

#include <iostream>
using namespace std;
class Tri;
class CRectangle {
        int width, height;
    public:
        void set_values(int a, int b) {
            width = a;
            height = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
class Tri {
        int W, H;
    public:
        Tri(int a, int b)
        {
            W = a;
            H = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
int Sum(Tri T, CRectangle R)
{
    return T.W + R.width;
}
int main()
{
    CRectangle r;
    r.set_values(2, 3);
    Tri l(5, 10);
    cout << Sum(l, r) << endl;
    return 0;
}

This C++ code demonstrates the usage of friend functions across different classes. Here’s a breakdown of the code:

Class Declarations:

  • Two classes are declared: CRectangle and Tri.
  • CRectangle has two private data members width and height, and a member function set_values to set these values.
  • Tri has two private data members W and H, and a constructor to initialize them.

Friend Function Declaration:

  • Both classes declare a friend function named Sum. This means that Sum function can access the private members of both CRectangle and Tri.

Friend Function Implementation:

  • The Sum function takes objects of types Tri and CRectangle as arguments and returns the sum of their corresponding private members.
  • In this case, it returns the sum of W from the Tri object and width from the CRectangle object.

Main Function:

  • In the main function, an object r of type CRectangle is created and its set_values function is called to set its dimensions to 2×3.
  • Another object l of type Tri is created with dimensions 5×10.
  • The Sum function is called with objects l and r as arguments, and the result is printed.

Output:

  • Since the Sum function returns the sum of W from Tri and width from CRectangle, the output would be 5 + 2 = 7.

Friend Class:

Friend class is a class that is granted access to the private and protected members of another class. You declare a friend class by preceding its declaration with the friend keyword inside the class that it’s a friend of.

Example 4:

#include <iostream>
using namespace std;
class CSquare;
class CRectangle {
        int width, height;
    public:
        int area(void) {
            return (width * height);
        }
        void convert(CSquare);
};
class CSquare {
    private:
        int side;
    public:
        void set_side(int x)
        {
            side = x;
        }
        friend class CRectangle;
};
void CRectangle::convert(CSquare a)
{
    width = a.side;
    height = a.side;
}
int main()
{
    CSquare sqr;
    CRectangle rect;
    sqr.set_side(4);
    rect.convert(sqr);
    cout << rect.area() << endl;
    return 0;
}

This C++ code demonstrates the usage of friend classes and member functions, particularly in the context of a CRectangle class and a CSquare class.

Class Declarations:

  • Two classes are declared: CRectangle and CSquare.
  • CRectangle has two private data members width and height, and a member function area to calculate its area. It also has a member function convert, which is later defined outside the class.
  • CSquare has one private data member side and a member function set_side to set its value. It declares CRectangle as a friend class.

Friend Class Declaration:

  • CSquare declares CRectangle as a friend class, allowing CRectangle to access its private members.

Member Function Definition:

  • The convert member function of CRectangle is defined outside of the class.
  • It takes a CSquare object as a parameter and assigns its side to both width and height of the CRectangle.

Main Function:

  • In the main function, objects sqr of type CSquare and rect of type CRectangle are created.
  • set_side function of sqr sets its side to 4.
  • convert function of rect is called with sqr as an argument, converting the square into a rectangle.
  • The area of the resulting rect is then printed.

Output:

  • Since the side of the square is 4, after converting it to a rectangle, both width and height of the rectangle become 4. Therefore, the area of the resulting rectangle is 4 * 4 = 16.

Operator Overloading

Operator overloading in C++ is a feature that allows you to redefine the behavior of operators (such as +, -, *, /, etc.) for user-defined types. It enables you to extend the functionality of operators to work with objects of your own classes.

Example 1:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        void add(triangle c1, triangle c2)
        {
            width = c1.width + c2.width;
            height = c1.height + c2.height;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3.add(c1, c2);
    c3.showdata();
    return 0;
}

This C++ code defines a class triangle representing a triangle. The class has private data members width and height, a constructor to initialize them, member functions getdata to input values for width and height, showdata to display the width and height, and add to add two triangles together.

Class Definition:

  • The triangle class is defined with private data members width and height.
  • It has a constructor that initializes width and height with default values of 0.
  • It contains member functions getdata, showdata, and add.

Main Function:

  • In the main function, three triangle objects are created: c1, c2, and c3.
  • c1 is initialized with default values using the default constructor.
  • c2 is initialized with values 3.5 and 1.5 using the parameterized constructor.
  • c3 is created without any initialization.
  • getdata is called for c1 to input values for width and height.
  • add is called for c3 with c1 and c2 as arguments, which adds the corresponding width and height of c1 and c2 and assigns the result to c3.
  • showdata is called for c3 to display the resulting width and height after addition.

Example 2:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle add(triangle c2)
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1.add(c2);
    c3.showdata();
    return 0;
}

In this example, the addition of two triangles is also performed using a member function named add. However, instead of modifying the object on which the function is called, a new triangle object is created inside the add function to store the result of the addition. This new object is then returned from the function, leaving the original objects unchanged.

Example 3:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle operator+(triangle c2) // Overloading the + operator
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1 + c2;  // Using the overloaded + operator
    c3.showdata();
    return 0;
}

This C++ code demonstrates the usage of operator overloading to perform addition between two triangle objects. Let’s break down the code and highlight the differences compared to the previous examples:

Differences compared to previous examples:

  1. Operator Overloading:
    In this example, the + operator is overloaded using a member function named operator+. This allows us to perform addition between two triangle objects using the + operator in a manner similar to built-in types.
    In contrast, the previous examples used member functions (add) to perform addition between objects.
  2. Usage in main Function:
    In the main function, the addition of c1 and c2 is performed using the + operator: c3 = c1 + c2;.
    This syntax is more intuitive and concise compared to calling a separate member function (add).
  3. Return Type:
    The operator+ function returns a triangle object representing the result of the addition.
    In the previous examples, the add functions did not return any value and instead modified one of the objects directly.

this Pointer

In object-oriented programming (OOP) languages like C++, the this pointer is a keyword that is used to refer to the current object within a member function. It is a special pointer that holds the memory address of the current object instance.

Example 1:

#include <iostream>
using namespace std;
class stud {
    public:
        void address() {
            cout << this;
        }
};
int main()
{
    stud a, b, c;
    cout << "The adress of a\t";
    a.address();
    cout << endl << "The adress of b\t";
    b.address();
    cout << endl << "The adress of c\t";
    c.address();
    cout << endl;
    return 0;
}

In this C++ code, we have a class named stud, which contains a member function address(). This member function simply prints the memory address of the current object using the this pointer.

Function of this Pointer:

  • In the address() function of the stud class, this refers to the current object for which the member function is being called.
  • Inside the address() function, cout << this; prints the memory address of the current object.
  • In the main() function, we create three objects a, b, and c of the class stud.
  • We then call the address() function on each object, which prints the memory address of each object.
  • The this pointer ensures that the correct memory address of the current object is printed when address() function is called for each object.

Example 2:

#include <iostream>
using namespace std;
class Student {
        int id;
    public:
        void set_id(int id) {
            this->id = id;
        }
        void print_id() {
            cout << "ID is " << id << endl;
        }
};
int main()
{
    Student St;
    St.set_id(10);
    St.print_id();
    return 0;
}

In this C++ code, we have a class named Student with a private member variable id representing the student’s ID. The class provides two member functions: set_id() and print_id().

Function of this Pointer:

  • In the set_id() member function, the parameter id passed to the function has the same name as the member variable id of the class. To distinguish between them, the this pointer is used.
  • Inside the set_id() function, this->id = id; assigns the value of the parameter id to the member variable id of the current object.
  • The this pointer points to the current object for which the member function is called. It is used to access members of the object.
  • In the main() function, an object St of the class Student is created. The set_id() function is called to set the ID of the St object to 10.
  • Then, the print_id() function is called to print the ID of the St object.

The output of the code will be:

ID is 10

 

Operator Overloading/Unary operator

In C++, operator overloading refers to the ability to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Unary operators are those operators that operate on a single operand. Overloading unary operators allows you to customize their behavior when applied to objects of your own classes.

Purpose of Operator Overloading:

  1. Provide Natural Syntax: Operator overloading allows you to use operators with user-defined types in a way that mimics their usage with built-in types. For example, you can add two objects of a class using the + operator, concatenate strings using the + operator, or increment an object using the ++ operator.
  2. Enhance Readability: By overloading operators, you can make your code more intuitive and readable, as it allows you to express operations in a natural and concise way.

Example 1:

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary. Let’s break down the code:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the unary ++ operator as a member function
    void operator++() {
        x++;
        y++;
    }
};

int main() {
    Unary v(10, 20);
    v++; // Incrementing the object 'v' using overloaded ++ operator
    v.show(); // Displaying the updated values of 'x' and 'y'

    return 0;
}

Explanation:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded using the operator++() member function. This function increments the values of x and y.
  • In the main() function, an object v of the Unary class is created with initial values 10 for x and 20 for y.
  • The ++ operator is applied to the object v using v++. Since it’s a unary operator, it doesn’t require any operand.
  • The overloaded operator++() function increments the values of x and y by one.
  • After the increment operation, the show() function is called to display the updated values of x and y.

The output of the code will be:

11 21

This is because the values of x and y are incremented by 1 after the ++ operator is applied to the object v. Thus, the updated values are displayed as 11 for x and 21 for y.

Example 2:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
};
int main()
{
    Unary v(10, 20), k;
    v++;
    k = v++;
    k.show();
    v.show();

    return 0;
}

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary, along with the postfix increment operator ++ that takes an additional dummy integer parameter. Let’s break down the code:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded twice:
    1. The operator++() function overloads the prefix ++ operator. It increments the values of x and y and returns the updated object.
    2. The operator++(int) function overloads the postfix ++ operator with an additional dummy integer parameter. It creates a temporary object t and assigns the current object’s values to it. Then, it increments the values of x and y of the current object and returns the temporary object t.
  • In the main() function, two objects v and k of the Unary class are created, with v initialized with values 10 for x and 20 for y.
  • v++ is applied to increment v using the postfix increment operator. This will increment the values of x and y of v and return a temporary object with the original values.
  • k = v++ will first assign the temporary object (with original values) to k and then increment v using the postfix increment operator.
  • The show() function is called to display the values of k and v after the increment operations.

The output of the code will be:

11 21
12 22

Example 3:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the prefix ++ operator
    Unary operator++() {
        x++;
        y++;
        return *this;
    }

    // Overloading the postfix ++ operator with an additional dummy integer parameter
    Unary operator++(int) {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }

    // Overloading the unary - operator
    Unary operator-() {
        x = -x;
        y = -y;
        return *this;
    }
};

int main() {
    Unary k(1, 2); // Create an object of the class Unary with initial values 1 and 2
    -k; // Applying unary - operator to object k
    k.show(); // Display the updated values of k

    return 0;
}
  • The operator-() function overloads the unary – operator. It negates the values of x and y by multiplying them by -1 and returns the updated object.
  • In the main() function, an object k of the Unary class is created with initial values 1 for x and 2 for y.
  • The unary – operator is applied to the object k using -k. This will negate the values of x and y of k.
  • Finally, the show() function is called to display the updated values of x and y.

This indicates that the values of x and y of object k have been negated by applying the unary – operator. Therefore, x becomes -1 and y becomes -2.

Example 4:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
};
int main()
{
    Unary x(1, 1);
    if (!x)
        cout << "true";
    else
        cout << "false";

    return 0;
}
  • The operator!() function overloads the logical negation operator !. It returns true if both x and y are equal to 0, indicating that the object is logically false. Otherwise, it returns false.
  • In the main() function, an object x of the Unary class is created with initial values 1 for x and 1 for y.
  • The logical negation operator ! is applied to the object x using !x. If x is logically false (i.e., both x and y are 0), it prints “true”. Otherwise, it prints “false”.

The output of the code will be:

false

Example 5:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
    Unary operator+=(Unary b2)
    {
        x += b2.x;
        y += b2.y;
        return *this;
    }
};
int main()
{
    Unary b(1, 2), b2(3, 3);
    b += b2;
    b.show();
    
    return 0;
}

the operator+=() function overloads the compound assignment operator +=. It adds the corresponding member variables of the current object (this) with the member variables of the passed object (b2) and returns the updated object.

The output of the code will be:

4 5

 

Operator Overloading/Relational Operator

In C++, operator overloading allows you to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Relational operators are used to compare values between two operands and determine the relationship between them. Operator overloading for relational operators allows you to define custom comparison behaviors for objects of your own classes.

Purpose of Operator Overloading for Relational Operators:

  1. Custom Comparison: With operator overloading, you can define custom comparison behaviors for objects of your classes. This allows you to compare objects based on specific criteria relevant to your application domain.
  2. Natural Syntax: Overloaded relational operators enable you to use the familiar syntax of relational operators (<, <=, >, >=, ==, !=) with user-defined types. This improves code readability and makes your code more intuitive.

Example:

#include <iostream>
using namespace std;
class Relational {
        int x, y, z;
    public:
        Relational()
        {
            x = y = z = 0;
        }
        Relational(int i, int j, int k)
        {
            x = i;
            y = j;
            z = k;
        }
        int operator==(Relational b)
        {
            return(x == b.x && y == b.y && z == b.z);
        }
};
int main()
{
    Relational a(10, 10, 10), b(10, 10, 10);
    if (a == b)
        cout << "The two objects are equal\n";
    else
        cout << "The two objects are not equal\n";
    
    return 0;
}

This C++ code demonstrates operator overloading for the equality (==) operator in the Relational class.

  • The Relational class represents objects with three integer attributes x, y, and z.
  • The class provides two constructors: one default constructor that initializes all attributes to 0, and another constructor that allows initializing the attributes with provided values.
  • The operator= = function is overloaded inside the class. It takes another Relational object b as a parameter and returns an integer indicating whether the attributes of the two objects are equal. It checks if the x, y, and z attributes of both objects are equal and returns 1 if they are, and 0 otherwise.
  • In the main() function, two Relational objects a and b are created, both initialized with the values (10, 10, 10).
  • The overloaded equality operator == is used to compare objects a and b. If the attributes of both objects are equal, the message “The two objects are equal” is printed; otherwise, the message “The two objects are not equal” is printed.

else if

First Project in C++

 

Example:

C++

#include <iostream>
int main()
{ 
    std::cout << "Welcome to C++";
    return 0;
}


This is a simple C++ program that prints the message “Welcome to C++” to the console.

  • #include <iostream>: This line tells the compiler to include the header file iostream. This header file contains declarations for the standard input/output library.
  • int main(): This line defines the main function. The main function is the entry point for all C++ programs.
  • std::cout << “Welcome to C++”;: This line prints the message “Welcome to C++” to the console using the std::cout object.
  • return 0;: This line returns the value 0 from the main function. This indicates that the program terminated successfully.

When you compile and run this program, the following output will be printed to the console:

Welcome to C++

This is a very simple example of a C++ program, but it illustrates some of the basic concepts of the language, such as header files, functions, and input/output.

STL C++

The Standard Template Library (STL) encompasses a collection of C++ template classes designed to furnish essential programming data structures and functionalities, including lists, stacks, arrays, and more. This library comprises container classes, algorithms, and iterators, making it a versatile toolset. STL’s components are parameterized, contributing to its generality. Proficiency in working with template classes is a prerequisite for effectively utilizing STL.

Introduction to Standard Template Library

The Standard Template Library (STL) is a powerful collection of classes and functions in C++ that provides reusable, generic algorithms, containers, and iterators. It’s an essential component of modern C++ programming and offers a wealth of functionality to simplify and enhance your code.

Key Components of STL:

  1. Containers:
    Containers are objects that store collections of other objects. They provide a way to organize and manipulate data efficiently. STL provides several container classes, each with its unique characteristics:
    – Vector: Dynamic array that automatically adjusts its size.
    – List: Doubly linked list that allows for fast insertions and deletions anywhere in the list.
    – Deque: Double-ended queue that supports fast insertion and deletion at both ends.
    – Set: Collection of unique, sorted elements.
    – Map: Collection of key-value pairs, where each key is unique.
    – Stack: Container with Last-In-First-Out (LIFO) access.
    – Queue: Container with First-In-First-Out (FIFO) access.
  2. Iterators:
    Iterators are objects that allow traversal through the elements of a container. They act as pointers and provide a uniform way to access the elements regardless of the underlying container implementation. There are different types of iterators:
    – Input iterators: Allow reading elements from a container.
    – Output iterators: Allow writing elements to a container.
    – Forward iterators: Support forward traversal.
    – Bidirectional iterators: Support bidirectional traversal (forward and backward).
    – Random access iterators: Support random access to elements (e.g., accessing elements by index).
  3. Algorithms:
    Algorithms are functions that operate on containers through iterators. They perform various operations such as searching, sorting, modifying, and manipulating elements in containers. STL provides a wide range of algorithms for common tasks, including:
    – Sorting: Sort elements in a container.
    – Searching: Search for elements in a container.
    – Transforming: Modify elements in a container based on certain criteria.
    – Copying: Copy elements between containers.
    – Merging: Merge elements from multiple containers into one sorted container.
    And many more…

Types of Container

  1. Simple
    – Pair
  2. Sequence
    – Array
    – Vector
    – Deque
    – List
    – Forward list
  3. Associative
    – Map
    – Multimap
    – Set
    – Multiset
  4. Unordered
    – Unordered set
    – Unordered multiset
    – Unordered map
    – Unordered multimap
  5. Adapter
    – Stack
    – Queue
    – Priority queue

Vector Part 1

Sequence containers in C++ are a category of containers within the Standard Template Library (STL) that store elements in a sequential order. They provide dynamic storage allocation and support various operations for accessing, inserting, and removing elements. Sequence containers are primarily categorized based on how they organize and manage their elements. Here’s an explanation of the commonly used sequence containers:

Arrays

Arrays are considered as a kind of sequence container in C++. However, they are typically categorized separately from other sequence containers like vectors, lists, and deques because of their fixed size nature and the absence of dynamic resizing capabilities.

Vector

Characteristics:

  1. Fast insert/ remove at the end
  2. Slow insert/ remove at the beginning or in the middle
  3. Slow search

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(4);
    v[0] = 10;
    v.push_back(50);

    return 0;
}

This code snippet attempts to create a vector of integers with an initial size of 4 elements, assigns a value to the first element, and then tries to add an additional element using the push_back function. However, there’s a potential issue with the usage of push_back after specifying the initial size.

Let’s analyze the code and discuss the implications:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(4);  // Creates a vector with 4 elements, all initialized to 0

    v[0] = 10;          // Assigns a value of 10 to the first element of the vector

    v.push_back(50);    // Attempts to add an additional element with the value 50
                        // This line may lead to undefined behavior because it's 
                        // appending an element beyond the originally specified size

    return 0;
}

Explanation:

  • The line vector<int> v(4); creates a vector v with an initial size of 4 elements, all initialized to the default value of integers (which is 0).
  • Then, v[0] = 10; assigns a value of 10 to the first element of the vector.
  • However, the subsequent line v.push_back(50); attempts to add an additional element to the vector using push_back. Since the vector was initially sized to contain only 4 elements, appending an element beyond this size may cause undefined behavior. The push_back operation might trigger a reallocation of the vector’s underlying storage, which could lead to memory corruption or other unexpected behavior.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4};  // Initialize vector v with values 1, 2, 3, 4
    vector<int>v2(v);             // Initialize vector v2 as a copy of v
    cout << v2[0];                // Output the first element of v2

    return 0;
}

This code snippet initializes a vector v with four integers {1, 2, 3, 4}, and then attempts to initialize another vector v2 as a copy of v.
The output will be 1, as it prints the first element of v2, which is a copy of v. Therefore, it will print the first element of v, which is 1.

Example 3:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100. This constructor initializes v with 5 elements, each having the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200. This constructor initializes v2 with 6 elements, each having the value 200.
  • cout << v2[0] << endl; prints the first element of v2, which is 200, followed by a newline character.

So, the output of this code will be:

200

Example 4:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    v.swap(v2);               // Swap the contents of v and v2
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200.
  • v.swap(v2); exchanges the contents of v and v2, effectively swapping the elements and sizes of the two vectors.
  • cout << v2[0] << endl; attempts to print the first element of v2.

However, after the swap operation, v2 now contains the elements originally in v, and v contains the elements originally in v2. Therefore, attempting to access v2[0] will actually print the first element of the vector that was initially v.

So, the output of this code will be:

100

Example 5:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v;           // Create an empty vector

    v.push_back(10);         // Add 10 to the end of the vector
    v.push_back(20);         // Add 20 to the end of the vector
    v.push_back(30);         // Add 30 to the end of the vector

    cout << v.front() << endl;  // Output the first element of the vector
    cout << v.back() << endl;   // Output the last element of the vector
    cout << v.at(0) << endl;    // Output the element at index 0 of the vector

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v;: Declares an empty vector of integers.
  • v.push_back(10);: Appends the value 10 to the end of the vector v.
  • v.push_back(20);: Appends the value 20 to the end of the vector v.
  • v.push_back(30);: Appends the value 30 to the end of the vector v.
  • cout << v.front() << endl;: Outputs the first element of the vector v using the front() member function. In this case, it prints 10.
  • cout << v.back() << endl;: Outputs the last element of the vector v using the back() member function. In this case, it prints 30.
  • cout << v.at(0) << endl;: Outputs the element at index 0 of the vector v using the at() member function. In this case, it prints 10.

So, the output of this code will be:

10
30
10

Example 6:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(100);   // Create a vector with 100 elements, all initialized to 0

    v.push_back(5);       // Append the value 5 to the end of the vector
    cout << "Size = " << v.size() << endl;        // Output the current size of the vector
    cout << "Capacity = " << v.capacity() << endl; // Output the current capacity of the vector

    return 0;
}

Here’s what each line does:

  • vector<int> v(100);: Creates a vector v with an initial size of 100 elements, all initialized to the default value of int, which is 0.
  • v.push_back(5);: Appends the value 5 to the end of the vector. Since the vector was initialized with a size of 100, but only one element was added, the vector will resize itself as needed to accommodate the new element.
  • cout << “Size = ” << v.size() << endl;: Outputs the current size of the vector using the size() member function. In this case, it prints 101, as there are now 101 elements in the vector.
  • cout << “Capacity = ” << v.capacity() << endl;: Outputs the current capacity of the vector using the capacity() member function. The capacity represents the maximum number of elements that the vector can hold without reallocating memory. In this case, it depends on the implementation, but it’s likely to be greater than or equal to 101, as the vector may allocate additional memory to avoid frequent reallocations when more elements are added.

Example 7:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4, 5};
    for (size_t i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {1, 2, 3, 4, 5};: Initializes a vector v with five elements, each containing the values 1, 2, 3, 4, and 5, respectively.
  • for (size_t i = 0; i < v.size(); i++) { … }: This is a traditional for loop that iterates over each element of the vector. It starts with an index i of 0 and continues until i is less than the size of the vector (v.size()).
  • size_t is an unsigned integer type used for representing sizes of objects. It’s commonly used for indices and sizes of containers like vectors.
  • cout << v[i] << ” “;: Within the loop, it prints the value of the element at index i of the vector, followed by a space.

So, the output of this code will be:

1 2 3 4 5

It prints each element of the vector v separated by a space.

 

Deque

Characteristics:

  1. Fast insert/ remove at the beginning and at the end
  2. Slow insert/ remove at the middle
  3. Slow research

List

Characteristics:

  1. Fast insertion and removal of elements from anywhere in the container
  2. Fast random access is not supported. It’s slow at accessing items from the middle
  3. Slow search
  4. Doubly-linked list

Forward List

Characteristics:

  1. First insertion and removal of elements from anywhere in the container
  2. Fast random access isn’t supported
  3. Singly-linked list

Vector Part 2

Iterators

In C++, iterators are objects that provide a way to traverse the elements of a container (such as vectors) in a sequential manner. Iterators act as pointers to elements in the container, allowing you to access and manipulate the elements efficiently. They serve as a bridge between algorithms and data structures, enabling you to perform various operations on container elements without needing to know the underlying implementation details.

For vectors specifically, iterators offer several functionalities:

  1. Accessing Elements: You can use iterators to access individual elements of a vector. Iterators support dereferencing, which allows you to retrieve the value of the element they point to.
  2. Traversal: Iterators provide mechanisms for traversing through the elements of a vector sequentially. You can increment or decrement an iterator to move to the next or previous element, respectively.
  3. Range-Based Operations: Iterators can define ranges within a vector, allowing you to perform operations on subsets of elements. For example, you can specify a range of iterators to indicate a subset of elements to sort or to copy to another container.
  4. Iterator Categories: Iterators in C++ are classified into different categories based on their capabilities and behavior. For vectors, the most commonly used iterator category is the random access iterator, which supports efficient random access to elements using arithmetic operations like addition and subtraction.
  5. Iterator Invalidation: Modifying a vector (e.g., inserting or erasing elements) can invalidate iterators pointing to elements within the vector. It’s essential to be aware of iterator invalidation rules to avoid undefined behavior when working with iterators.

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.begin();
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {10, 20, 30, 40};: Initializes a vector v with four integers {10, 20, 30, 40}.
  • vector<int>::iterator it = v.begin();: Declares an iterator it of type vector<int>::iterator and initializes it to point to the beginning of the vector v using the begin() member function.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the first element of the vector) and prints it using cout.

It prints the value of the first element of the vector v, which is 10.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.end()-1;
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int>::iterator it = v.end() – 1;: Declares an iterator it of type vector<int>::iterator and initializes it to point to the last element of the vector v by subtracting 1 from the result of the end() member function. Note that end() returns an iterator pointing to the position after the last element, so subtracting 1 points it to the last element.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the last element of the vector) and prints it using cout.

It prints the value of the last element of the vector v, which is 40.

Example 3:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over each element of the vector using an iterator it. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator is equal to v.end(), which represents one position past the end of the vector. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
20
30
40

Example 4:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int>v = {10, 20, 30, 40};

for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
{
cout << *it << endl;
}

return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using reverse iterators. It starts with the reverse iterator it pointing to the last element of the vector (v.rbegin()) and continues until the reverse iterator reaches the position before the first element (v.rend()), exclusive. In each iteration, the reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

40
30
20
10

Example 5:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using const reverse iterators. It starts with the const reverse iterator it pointing to the last element of the vector (v.crbegin()) and continues until the const reverse iterator reaches the position before the first element (v.crend()), exclusive. In each iteration, the const reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v in reverse order, starting from 40 and ending with 10.

Example 6:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++) { … }: This is a for loop that iterates over the vector elements using const iterators. It starts with the const iterator it pointing to the first element of the vector (v.cbegin()) and continues until the const iterator reaches the position after the last element (v.cend()), exclusive. In each iteration, the const iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v on a new line, iterating through the entire vector.

Auto

In C++, the auto keyword is used for type inference, allowing the compiler to automatically deduce the type of a variable based on its initializer. When used with vectors, auto can simplify code by automatically determining the correct type of iterators or elements without explicitly specifying it.

Using auto with vectors can make the code more concise and readable, especially when the iterator or element type is complex or when it’s changed frequently. However, it’s essential to use auto judiciously and ensure that the deduced type is clear and unambiguous.

Example 7:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {5, 10, 15, 20};  // Initialize vector v with four integers

    auto it = v.begin();  // Use auto to deduce the type of the iterator

    // Iterate over the vector elements using the deduced iterator type
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output the value pointed to by the iterator, followed by a newline
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {5, 10, 15, 20};: Initializes a vector v with four integers {5, 10, 15, 20}.
  • auto it = v.begin();: Uses auto to deduce the type of the iterator it. In this case, it deduces that it is of type vector<int>::iterator, pointing to the beginning of the vector v.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using the deduced iterator type. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
10
15
20

Example 8:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.insert(v.begin()+1, 12);
    v.insert(v.end()-1, 17);
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.insert(v.begin() + 1, 12);: Inserts the value 12 into the vector v at the position after the first element (index 1).
  • v.insert(v.end() – 1, 17);: Inserts the value 17 into the vector v at the position before the last element. Since v.end() points to one past the last element, subtracting 1 positions the insertion point before the last element.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
12
10
15
17
20

Example 9:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin());: Removes the first element from the vector v using the erase() method. Since v.begin() points to the first element, this operation removes that element from the vector.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
15
20

Example 10:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin()+1, v.end());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin() + 1, v.end());: Removes elements from the second element (index 1) until the end of the vector using the erase() method with iterators defining the range. The range is specified from v.begin() + 1 (the iterator pointing to the second element) to v.end() (the iterator pointing one past the last element).
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the remaining vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last remaining element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the remaining element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5

Example 11:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(10);
    
    for (int i = 0; i <10; i++)
        v[i] = i;
    
    cout << "Vector size initially: " << v.size();
    cout << "\nVector elemens are: ";
    for (int i = 0; i <10; i++)
        cout << v[i] << " ";
        
    v.resize(5);
    cout << "\n\nVector size after resize(5): " << v.size();
    v.shrink_to_fit();
    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(10);: Initializes a vector v with size 10, containing default-initialized elements (all elements are initialized to zero in this case).
  • Assigns values to the elements of the vector using a loop.
  • Outputs the initial size of the vector using v.size().
  • Outputs the elements of the vector using a loop.
  • Resizes the vector to size 5 using v.resize(5). This operation reduces the size of the vector to 5, and any excess elements are removed from the vector.
  • Outputs the size of the vector after resizing.
  • Calls v.shrink_to_fit() to reduce the capacity of the vector to match its size.

Note: shrink_to_fit() is a non-binding request to reduce the capacity of the vector to fit its size but does not guarantee that the capacity will actually be reduced. The implementation may choose to ignore the request.

 

Vector Part 3

Example 1:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5);  // Initialize vector v with size 5
    int n = 0;

    // Prompt the user to enter vector elements
    cout << "Enter Vector Elements:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cin >> v[i];  // Read input into vector element at index i
        
        // Check if we're at the end of the vector
        if (i == v.size() - 1) {
            cout << "If you want to resize the list, enter the new size. Enter -1 to finish: ";
            cin >> n;
            if (n == -1)
                break;
            else
               v.resize(n);  // Resize the vector to the new size entered by the user
        }
    }

    // Output the elements of the vector
    cout << "Vector elements are:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cout << v[i] << endl;  // Output each element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(5);: Initializes a vector v with size 5, containing default-initialized elements (all elements are initialized to zero in this case).
  • Prompts the user to enter vector elements.
  • Reads input from the user into the vector elements using a loop. After reading the last element, the code prompts the user to either resize the vector or exit the loop by entering -1.
  • If the user enters a new size, the vector is resized accordingly using v.resize(n).
  • Outputs the elements of the vector after the loop ends.

This code allows the user to dynamically resize the vector during input and then displays the elements of the vector.

Example 2:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some unsorted integers

    sort(v.begin(), v.end());  // Sort the elements of the vector in ascending order

    // Output the sorted elements of the vector
    for (auto it : v) {
        cout << it << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in an unsorted order.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm. The sort function requires two iterators specifying the range to be sorted, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).
  • for (auto it : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in ascending order.
  • cout << it << endl;: Within the loop, it prints each element it of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
3
5
7

It prints each element of the sorted vector v in ascending order, one element per line.

Example 3:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    sort(v.rbegin(), v.rend());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}

Here’s what each part of the code does:

  • sort(v.rbegin(), v.rend());: Sorts the elements of the vector v in descending order using the std::sort algorithm with reverse iterators. The sort function requires two iterators specifying the range to be sorted, which are v.rbegin() (pointing to the last element, treated as the first for sorting) and v.rend() (pointing to one before the first element, treated as the last for sorting).

So, the output of this code will be:\

7
5
3
2
1
0

It prints each element of the sorted vector v in descending order, one element per line.

Example 4:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    reverse(v.begin(), v.end());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}
  • reverse(v.begin(), v.end());: Reverses the elements of the vector v using the std::reverse algorithm. The reverse function requires two iterators specifying the range to be reversed, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).

So, the output of this code will be:

3
0
7
2
1
5

It prints each element of the reversed vector v, one element per line.

Example 5:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find and output the minimum element in the vector
    cout << *min_element(v.begin(), v.end()) << endl;

    // Find and output the maximum element in the vector
    cout << *max_element(v.begin(), v.end()) << endl;

    // Find and output the minimum element in the vector excluding the last two elements
    cout << *min_element(v.begin(), v.end() - 2) << endl;

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in the given order.
  • cout << *min_element(v.begin(), v.end()) << endl;: Finds the minimum element in the vector v using the std::min_element algorithm. The min_element function returns an iterator pointing to the minimum element, and * dereferences this iterator to obtain the value of the minimum element. The minimum element is then printed followed by a newline.
  • cout << *max_element(v.begin(), v.end()) << endl;: Similar to above, this line finds and prints the maximum element in the vector v.
  • cout << *min_element(v.begin(), v.end() – 2) << endl;: Finds the minimum element in the vector v excluding the last two elements. The range used for finding the minimum element is from v.begin() to v.end() – 2 (excluding the last two elements). The minimum element is then printed followed by a newline.

So, the output of this code will be:

0
7
1

It prints the minimum element, maximum element, and minimum element excluding the last two elements of the vector v, each followed by a newline.

Example 6:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};

    auto pair = minmax_element(v.begin(), v.end());
    cout << *pair.first << endl;
    cout << *pair.second << endl;

    return 0;
}

Here’s what each part of the code does:

  • auto pair = minmax_element(v.begin(), v.end());: Finds both the minimum and maximum elements in the vector v using the std::minmax_element algorithm. This function returns a pair of iterators, where the first iterator points to the minimum element and the second iterator points to the maximum element.
  • cout << *pair.first << endl;: Outputs the value of the minimum element by dereferencing the iterator pair.first.
  • cout << *pair.second << endl;: Outputs the value of the maximum element by dereferencing the iterator pair.second.

So, the output of this code will be:

0
7

It prints the minimum and maximum elements of the vector v, each followed by a newline.

Example 7:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find the minimum element in the vector
    auto it = min_element(v.begin(), v.end());

    // Sort the elements of the vector up to (but not including) the minimum element
    sort(v.begin(), it);

    // Output the sorted elements of the vector
    for (auto i : v) {
        cout << i << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • auto it = min_element(v.begin(), v.end());: Finds the minimum element in the vector v using the std::min_element algorithm. This function returns an iterator pointing to the minimum element.
  • sort(v.begin(), it);: Sorts the elements of the vector v up to (but not including) the minimum element found by min_element. It uses the std::sort algorithm with a range specified by iterators, from v.begin() to it. This sorts the elements before the minimum element.
  • for (auto i : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in sorted order.
    cout << i << endl;: Within the loop, it prints each sorted element i of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
5
7

It prints each element of the vector v up to the minimum element, sorted in ascending order, each followed by a newline.

Example 8:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool GreaterThanThree(int i) {
    return i > 3;
}

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Sort the elements of the vector in ascending order
    sort(v.begin(), v.end());

    // Find the first element greater than 3 using find_if with GreaterThanThree as the predicate
    auto it = find_if(v.begin(), v.end(), GreaterThanThree);

    // Output all elements greater than 3
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output each element greater than 3 followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • bool GreaterThanThree(int i): Defines a predicate function GreaterThanThree that returns true if the input integer i is greater than 3.
  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm.
  • auto it = find_if(v.begin(), v.end(), GreaterThanThree);: Finds the first element greater than 3 in the sorted vector v using the std::find_if algorithm with the GreaterThanThree predicate function.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the elements from the first element greater than 3 until the end of the vector. It outputs each element greater than 3 followed by a newline using cout.

So, the output of this code will be:

5
7

It prints each element of the vector v that is greater than 3, each followed by a newline.

Example 9:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool GreaterThanThree(int i)
{
    return i > 3;
}
int main()
{
    int arr[] = {10, 20, 30, 40, 50, 60, 70};
    vector<int> v(7);
    copy(arr, arr + 7, v.begin());
    cout << "myvector contains: ";
    for (auto it:v)
        cout << it << " ";
    return 0;
}

Here’s what each part of the code does:

  • int arr[] = {10, 20, 30, 40, 50, 60, 70};: Initializes a C-style array arr with seven integers.
  • vector<int> v(7);: Initializes a vector v with size 7.
  • copy(arr, arr + 7, v.begin());: Copies elements from the C-style array arr to the vector v using the std::copy algorithm. The copy function requires three parameters: the beginning and end iterators of the source range (here, arr and arr + 7 representing the whole array), and the beginning iterator of the destination range (here, v.begin()).
  • cout << “myvector contains: “;: Outputs a message indicating the start of the output.
  • for (auto it : v) cout << it << ” “;: This is a range-based for loop that iterates over the elements of the vector v. It outputs each element of the vector followed by a space.

So, the output of this code will be:

myvector contains: 10 20 30 40 50 60 70

Example 10:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    vector<int> to_vector(15);
    copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());
    cout << "to_vector contains: ";
    for (auto i: to_vector)
        cout << i << " ";
    return 0;
}

Here’s what each part of the code does:

  • vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};: Initializes a source vector from_vector with ten integers.
  • vector<int> to_vector(15);: Initializes a target vector to_vector with size 15.
  • copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());: Copies elements from the source vector from_vector to the target vector to_vector in reverse order using the std::copy_backward algorithm. The copy_backward function requires three parameters: the beginning and end iterators of the source range (here, from_vector.begin() and from_vector.end() representing the whole vector), and the end iterator of the destination range (here, to_vector.end()).
  • cout << “to_vector contains: “;: Outputs a message indicating the start of the output.
  • for (auto i : to_vector) cout << i << ” “;: This is a range-based for loop that iterates over the elements of the target vector to_vector. It outputs each element of the target vector followed by a space.

So, the output of this code will be:

to_vector contains: 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10

It prints each element of the target vector to_vector, which contains the elements of the source vector from_vector copied in reverse order, followed by a space. The initial elements of to_vector that were not overwritten by the copy operation are left unchanged (default-initialized to 0 in this case).

Example 11:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3, 4, 5};  // Initialize a vector v with five integers

    // Copy elements from the vector v to the standard output (cout)
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

Here’s what each part of the code does:

  • copy(v.begin(), v.end(), ostream_iterator<int>(cout, ” “));: Copies elements from the vector v to the standard output (cout) using the std::copy algorithm and std::ostream_iterator. The copy function requires three parameters: the beginning and end iterators of the source range (here, v.begin() and v.end() representing the whole vector), and the output iterator (here, ostream_iterator<int>(cout, ” “)) that writes each copied element to the standard output with a space separator.

So, the output of this code will be:

1 2 3 4 5

Properties of vector

  1. Add -> Back -> O(1):
    This line indicates that adding an element to the back (end) of a vector has a time complexity of O(1), meaning it’s a constant-time operation. Vectors have dynamic memory allocation, and adding an element to the back typically involves appending the element to the end of the underlying contiguous memory block, which can be done in constant time.
  2. Delete -> Back -> O(1):
    Deleting an element from the back (end) of a vector also has a time complexity of O(1), which means it’s a constant-time operation. Removing the last element usually involves decrementing the size of the vector, and no reallocation or shifting of elements is required.
  3. Add -> Any Where -> O(N):
    Adding an element anywhere except the back of the vector, such as at the front or in the middle, has a time complexity of O(N). This is because inserting an element at an arbitrary position may require shifting all subsequent elements to make room for the new element, which takes linear time proportional to the number of elements shifted.
  4. Delete -> Any Where -> O(N):
    Similarly, deleting an element from anywhere except the back of the vector also has a time complexity of O(N). Removing an element from an arbitrary position may require shifting all subsequent elements to fill the gap left by the deleted element, which also takes linear time proportional to the number of elements shifted.
  5. Access -> [] – at() -> O(1):
    Accessing an element in a vector by index using the square brackets ([]) operator or the at() member function has a time complexity of O(1). This means that accessing any element in the vector takes constant time regardless of the size of the vector. Vectors provide constant-time random access because they store elements in a contiguous memory block, allowing for direct access to any element by its index.
  6. Search -> find() -> O(log N):
    Searching for an element in a sorted vector using the std::find() algorithm has a time complexity of O(log N) when the vector is sorted. This is because std::find() performs a binary search on the sorted vector, which has a logarithmic time complexity. However, it’s important to note that if the vector is not sorted, the time complexity of finding an element using std::find() would be O(N), as it performs a linear search.

Advantages:

Implemented as dynamic arrays

Drawbacks:

  1. Expensive reallocation
  2. Requires Contiguous Memory

Data Structures

A data structure serves as a repository designed for the storage and structured organization of data, enabling efficient access and updates when utilized on a computer.

Complexity

Introduction:

Complexity in data structures is a fundamental concept in computer science that helps us analyze the performance and efficiency of algorithms. It allows us to quantify the resources (such as time and memory) required by an algorithm to solve a problem as the input size grows. In this article, we’ll explore the basics of complexity in data structures, including time complexity and space complexity, and how they impact algorithm design and analysis.

In search algorithms, analyzing the efficiency requires considering different potential scenarios. This helps us understand how the algorithm performs under different circumstances. Here, we’ll explore base case, average case, and worst case along with their complexity notation:

  1. Base Case (Omega notation):
    Denotes the simplest input where the algorithm terminates in the least number of steps.
    Notation: Varies depending on the algorithm. Often denoted by O(1) which signifies constant time, independent of input size.
  2. Average Case (Theta notation):
    Represents the performance expected on average when considering all possible inputs with equal probability.
    Notation: Depends on the algorithm’s design and data distribution. For example, linear search has an average case of O(n/2), meaning it takes half the comparisons, on average, to find an element in a list.
  3. Worst Case (Big O notation):
    Represents the most challenging scenario, requiring the maximum number of steps.
    Notation: Again, depends on the algorithm. Linear search’s worst case is O(n), signifying it may need to compare all elements if the target is not present or at the end.
  • Further Note:
    – Complexity notation uses symbols like O, Ω, and Θ to represent how the execution time grows with input size (Big O Notation, Big Omega Notation, and Big Theta Notation respectively).
    – These representations provide an idealized theoretical understanding of the algorithm’s efficiency, not always guaranteeing exact execution times.

Big O notation

Big O notation is a mathematical tool used in computer science to describe the upper bound of how an algorithm’s execution time or space complexity grows as the input size increases. In simpler terms, it helps us understand how efficiently an algorithm performs as it deals with larger and larger datasets.

Here are some key points about Big O notation:

What it describes:

Big O notation focuses on the limiting behavior of a function (usually representing the algorithm’s complexity) as the input size tends towards infinity. It ignores constants and lower-order terms, providing a general idea of the algorithm’s efficiency, not the exact execution time.

Key notations:

  • O(n): This is the most common notation, meaning the function grows linearly with the input size (n). Doubling the input roughly doubles the execution time. Examples include searching an unsorted list (linear search) and iterating through all elements of an array.
  • O(log n): This signifies logarithmic growth, which is much faster than linear. Doubling the input only increases the execution time by a constant amount. Binary search is a classic example.
  • O(1): This represents constant time complexity, meaning the execution time is independent of the input size. Accessing an element directly in an array by its index is O(1).
  • O(n^2): This denotes quadratic growth, where the execution time increases quadratically with input size. Nested loops can often lead to O(n^2) complexity.
  • O(k^n): This represents exponential growth, which is generally undesirable due to its rapid increase in execution time with even small input size.

Interpreting Big O:

  • Lower values (O(1), O(log n)) are generally better as they indicate faster algorithms that scale well with larger inputs.
  • Higher values (O(n^2), O(k^n)) can be problematic for large datasets as they lead to significant performance bottlenecks.

Big O is not the only complexity measure:

While Big O focuses on upper bounds, there are other notations like Omega (Ω) for lower bounds and Theta (Θ) for exact bounds.

Example 1:

sum; // n = 5
for (i = 1; i <= n; i++)
sum = sum + 1;

This code calculates the sum of numbers from 1 to n using a for loop. The loop iterates n times, and within each iteration, it performs a constant-time addition operation (sum = sum + 1).

Therefore, the time complexity of this code is O(n). This means that the execution time of the code grows linearly with the input size n. In other words, as the value of n increases, the time it takes for the code to run will also increase, but at a proportional rate.

Here’s a table summarizing the time complexity analysis:

Step Description Time Complexity
Initialization Declare variables sum and i O(1)
Loop Iterate n times O(n)
Increment Add 1 to sum in each iteration O(n)
Total O(n)

Overall, the code has a linear time complexity, which is considered efficient for many algorithms.

Introduction to Stack

Introduction:

In the realm of computer science and programming, understanding data structures is fundamental. One such essential data structure is the stack. In this article, we’ll delve into what stacks are, how they work, their operations, and their applications in programming.

What is a Stack?

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. Imagine a stack of plates in a cafeteria; you can only take the top plate off the stack. Similarly, in a stack data structure, elements can only be added or removed from the top.

How Does a Stack Work?

A stack has two primary operations: push and pop.

  • Push: Adds an element to the top of the stack.
  • Pop: Removes the top element from the stack.

Additionally, stacks typically support other operations like peek (to view the top element without removing it) and isEmpty (to check if the stack is empty).

Stack Implementation:

Stacks can be implemented using arrays or linked lists.

  • Array Implementation: In this approach, a fixed-size array is used to store the stack elements. Push and pop operations modify the top index of the array.
  • Linked List Implementation: Here, a linked list is used to implement the stack. Each node in the linked list represents an element, and the top of the stack is the head of the list.

Stack Operations:

Let’s look at the stack operations in detail:

  • Push: Adds an element to the top of the stack. The new element becomes the top element, and the stack size increases by one.
  • Pop: Removes the top element from the stack. The element is returned (or simply removed), and the stack size decreases by one.
  • getTop: Returns the top element of the stack without removing it.
  • isEmpty: Checks if the stack is empty. Returns true if the stack is empty, and false otherwise.

Applications of Stacks:

Stacks find applications in various areas of computer science and programming, including:

  • Function Call Stack: Used to manage function calls and local variables in programming languages.
  • Expression Evaluation: Used to evaluate arithmetic expressions, infix-to-postfix conversion, and solving postfix expressions.
  • Undo Mechanism: Supports the undo operation in text editors and graphic design software.
  • Backtracking: Used in algorithms like depth-first search (DFS) to explore all possible paths in a graph.

Conclusion:

In conclusion, stacks are simple yet powerful data structures that play a crucial role in many programming tasks. Understanding how stacks work and their applications can significantly enhance a programmer’s problem-solving abilities. Whether you’re a beginner or an experienced programmer, mastering stacks is essential for building efficient and robust software systems.

 

Stack Implementation

This code defines a simple stack class with basic operations like push, pop, getTop, and print. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

const int MAX_SIZE = 100;

class Stack {
private:
    int top;            // Index of the top element in the stack
    int item[MAX_SIZE]; // Array to store stack elements

public:
    // Constructor: Initializes top to -1 (empty stack)
    Stack() : top(-1) {}

    // Function to push an element onto the stack
    void push(int Element) {
        if (top >= MAX_SIZE - 1) {
            cout << "Stack is full on push" << endl;
        } else {
            top++;
            item[top] = Element;
        }
    }

    // Function to check if the stack is empty
    bool isEmpty() {
        return top < 0;
    }

    // Function to pop an element from the stack
    void pop() {
        if (isEmpty()) {
            cout << "Stack is empty on pop" << endl;
        } else {
            top--;
        }
    }

    // Function to get the top element of the stack
    void getTop(int& stackTop) {
        if (isEmpty()) {
            cout << "Stack is empty on getTop" << endl;
        } else {
            stackTop = item[top];
            cout << stackTop << endl;
        }
    }

    // Function to print the elements of the stack
    void print() {
        cout << "[";
        for (int i = top; i >= 0; i--) {
            cout << item[i] << " ";
        }
        cout << "]" << endl;
    }
};

int main() {
    Stack s;

    // Push elements onto the stack
    s.push(5);
    s.push(10);
    s.push(15);
    s.push(20);

    // Print the stack
    s.print();

    // Get and print the top element of the stack
    int y = 0;
    s.getTop(y);

    // Pop an element from the stack
    s.pop();

    // Push another element onto the stack
    s.push(7);

    // Print the stack again
    s.print();

    return 0;
}

Explanation:

  • The Stack class implements a stack using an array named item. It has member functions for push, pop, getTop, isEmpty, and print.
  • In the push function, if the stack is not full, it increments the top index and adds the element to the item array at the top index.
  • The isEmpty function checks if the stack is empty by comparing the top index with -1.
  • The pop function decrements the top index if the stack is not empty.
  • The getTop function retrieves the top element of the stack and stores it in the stackTop parameter.
  • The print function prints the elements of the stack from top to bottom.
  • In the main function, a Stack object s is created and various operations like push, pop, getTop, and print are performed on it, demonstrating the usage of the stack.

 

Stack Using Linked List(Linked Stack)-Part 1

Introduction

We’ve covered the concepts of a stack and a stack implemented using arrays. Now, let’s explore the implementation of a stack using pointers and discuss why it’s considered a superior approach.

You might be wondering why we need to discuss this alternative when we’ve already looked at stack implementations using arrays. Can’t we just stick to arrays?

The reason for exploring stack implementation with pointers is to address potential limitations we might encounter with array-based implementations, particularly regarding size constraints. By utilizing pointers, we can effectively circumvent such issues, ensuring a more flexible and robust solution for managing data within a stack structure.

Using pointers to implement a stack involves dynamically allocating memory for the stack elements and manipulating pointers to manage the stack structure. This approach is particularly useful when the size of the stack is not known beforehand or when memory efficiency is a concern.

Node Structure

A “node” refers to a fundamental building block used in many data structures, including linked lists, trees, graphs, and more. A node is a structure that contains two main components:

  1. Data: This component holds the actual value or element that the node represents. It could be of any data type depending on the application.
  2. Next Pointer (or Link): This component is a reference or pointer to the next node in the sequence. It establishes the connection between nodes in the data structure.

These code snippets define a basic node structure in different programming languages:

  • C++:
    struct Node {
        Type item;
        Node* next;
    };
    

    In C++, struct is used to define a structure named Node. It contains two members:

    – item: A variable of type Type to store data.
    – next: A pointer to another Node, indicating the next node in the sequence.

  • Java:
    class Node {
        Type item;
        Node next;
    }
    

    In Java, class is used to define a class named Node. Similarly, it has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • C#:
    class Node {
        Type item;
        Node next;
    }
    

    This is similar to Java. In C#, class is used to define a class named Node, and it also has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • Python:
    class Node:
        def __init__(self):
            self.item = None
            self.next = None
    

    In Python, a class named Node is defined. The __init__ method is a constructor used to initialize objects of the class. Inside the constructor:

    – self.item is initialized to None, indicating that it stores data.
    – self.next is initialized to None, indicating that it refers to the next node in the sequence.

stackTop

stackTop typically refers to the top element of a stack data structure. In the context of a stack, it is a variable or pointer that points to the topmost element of the stack, or in other words, the most recently added element.

To assign the value of stackTop to the next member of a node:

  • C++:
    newNode is a pointer to a node, and stackTop is presumably another pointer to a node. This line assigns the value of stackTop to the next pointer of the newNode, effectively linking newNode to the node pointed to by stackTop.

    newNode->next = stackTop;
    
  • Java, C#, Python:
    newNode is an object of type Node, and stackTop is also an object of type Node. This line assigns the reference of the object referred to by stackTop to the next field of the newNode.

    newNode.next = stackTop; // Java and C#
    
    newNode.next = stackTop // Python

To assigns the value of newNode to stackTop:
C++, Java, C#, Python:

stackTop = newNode

stackTop is a pointer to the top element of a stack implemented using pointers or dynamic memory allocation. stackTop = newNode would update stackTop to point to the newly created node newNode. This effectively makes newNode the new top element of the stack.
To creates a copy of stackTop we use the statement:

temp = stackTop

Why do we do that?

Creating a copy of stackTop (temp) allows you to safely manipulate and access the top element of the stack without affecting the original pointer, reference, or value. It provides flexibility and ensures that the original data remains intact for future use.

A Pointer-Base Implementation of the ADT Stack(linked stack) main Functions:

  • push(Type newItem)
  • pop()
  • pop(Type& stackTop)
  • getTop()
  • display()
  • isEmpty()

While Loop

The while loop in C++ is a control statement that allows you to execute a block of code repeatedly while a condition is true. The general syntax of a while loop is as follows:

while (condition) {
  // code to execute while the condition is true
}

The condition can be any Boolean expression. The while loop evaluates the condition and if it is true, the code block inside the while loop is executed. The code block inside the while loop is executed repeatedly until the condition evaluates to false.

Here is an example of a while loop:

#include <iostream>

using namespace std;

int main()
{
    while (true)
    {
        cout << " a word" <<endl;
    }
    
    return 0;
}

The previous code is a simple infinite loop in C++. It will print the phrase “a word” to the console forever, or until the program is terminated.

The while (true) statement creates an infinite loop. This means that the code block inside the loop will be executed forever, or until the program is terminated.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler evaluates the condition of the while statement. Since the condition is always true, the code block inside the loop is executed.
  2. The compiler prints the phrase “a word” to the console.
  3. The compiler goes back to step 1 and repeats the process.

This process continues forever, or until the program is terminated.

To terminate the program, you can press Ctrl+C on your keyboard.

Here are some things to keep in mind about infinite loops:

  • Infinite loops can be useful for certain tasks, such as polling for input or waiting for a certain event to occur.
  • However, it is important to use infinite loops carefully, as they can also cause your program to crash if you are not careful.
  • For example, if you accidentally create an infinite loop that prints output to the console, your console window will quickly fill up with output and your program will become unresponsive.

To overcome these problems we should make 3 steps:

  1. declare a variable and initializes it to any value we want.
  2. add a condition to while statement.
  3. set a counter for our variable.

These steps are shown in the following example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0;
    while (c < 5)
    {
        cout << " a word" <<endl;
        c++;
    }
    
    return 0;
}

int c = 0;, declares an integer variable named c and initializes it to the value 0.

The while (c < 5) statement creates a loop that will iterate as long as the value of the c variable is less than 5.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

The c++; statement increments the value of the c variable by 1.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the c variable and initializes it to the value 0.
  2. The compiler evaluates the condition of the while statement. Since the condition is true, the code block inside the loop is executed.
  3. The compiler prints the phrase “a word” to the console.
  4. The compiler increments the value of the c variable by 1.
  5. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 5. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

Here is the output of this program:

a word
a word
a word
a word
a word

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    while (c < 4)
    {
        cout << "Enter a number: ";
        cin >> num;
        sum = sum + num;
        c++;
    }
    cout << " sum = " << sum << endl;
    return 0;
}

This code is a simple C++ program that prompts the user to enter four numbers and then prints the sum of those numbers to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The while (c < 4) statement creates a loop that will iterate as long as the value of the c variable is less than 4.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum = sum + num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 4. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

After the loop has terminated, the program prints the message ” sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
 sum = 100

While loops are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Here are some tips for using while loops:

  • Make sure that the condition of the while loop will eventually evaluate to false. Otherwise, the while loop will run forever.
  • Use a break statement to exit the while loop early.
  • Use a continue statement to skip the rest of the current iteration of the while loop.

Escape Sequence

Escape sequences are special characters that are used to represent non-printing characters or to control the behavior of output streams. They are prefixed with a backslash (\).

Types of Escape Sequences

There are three types of escape sequences in C++:

  • Character escape sequences: These escape sequences represent non-printing characters, such as newline, tab, and backspace.
  • Hexadecimal escape sequences: These escape sequences represent characters using their hexadecimal values.
  • Octal escape sequences: These escape sequences represent characters using their octal values.

Common Escape Sequences

Here are some of the most common escape sequences in C++:

Escape Sequence Description
\n Newline
\t Tab
\\ Backslash
\" Double quote
\' Single quote
\? Question mark
\a Alert
\b Backspace
\f Form feed
\r Carriage return
\v Vertical tab
\x Hexadecimal escape sequence
\NNN Octal escape sequence

Using Escape Sequences

Escape sequences can be used in string and character literals. For example, the following code prints the string “Hello, world!” followed by a newline character:

C++
std::cout << "Hello, world!" << std::endl;

The std::endl object represents the newline character. It is equivalent to the escape sequence \n.

Escape sequences can also be used to represent non-printing characters, such as the tab character. For example, the following code prints the string “Hello, world!” followed by a tab character:

C++
std::cout << "Hello, world!" << '\t';

Example

Here are some more examples of how to use escape sequences in C++:

C++
// Print the string "This is a quote \" inside a string." 
std::cout << "This is a quote \" inside a string."; 

// Print the character 'a' with a backspace before it. 
std::cout << '\b' << 'a';

// Print the string "Hello, world!" followed by a newline character and a tab character. 
std::cout << "Hello, world!" << std::endl << '\t';
Conclusion

Escape sequences are a powerful tool that can be used to control the behavior of output streams and to represent non-printing characters in C++.

Variables vs Data type

Variables vs Data types in C++

Variables

Variables are named memory locations that can store data. They are declared using the var_name : data_type syntax. For example, the following code declares a variable named my_integer that can store an integer value:

C++
int my_integer;

Once a variable is declared, it can be used to store and retrieve data. For example, the following code assigns the value 10 to the my_integer variable:

C++
my_integer = 10;

The following code prints the value of the my_integer variable to the console:

C++
std::cout << my_integer << std::endl;

Output:

10

Data types

Data types define the type of data that a variable can store. C++ has a variety of data types, including integers, floating-point numbers, characters, strings, and Boolean values.

Here are some examples of data types in C++:

  • int: Stores integer values
  • float: Stores floating-point numbers
  • char: Stores a single character
  • string: Stores a sequence of characters
  • bool: Stores a Boolean value (true or false)

When a variable is declared, it must be assigned a data type. This tells the compiler how much memory to allocate for the variable and what type of data it can store.

For example, the following code declares a variable named my_string that can store a string value:

C++
string my_string;

The string data type is a special data type that is used to store sequences of characters.

Example

Here is an example of how to use variables and data types in C++:

C++
int my_integer = 10;
float my_floating_point_number = 3.14159;
char my_character = 'a';
string my_string = "Hello, world!";
bool my_boolean_value = true;

// Print the values of the variables.
std::cout << my_integer << std::endl;
std::cout << my_floating_point_number << std::endl;
std::cout << my_character << std::endl;
std::cout << my_string << std::endl;
std::cout << my_boolean_value << std::endl;

Output:

10
3.14159
a
Hello, world!
true

Variables and data types are essential concepts in C++. By understanding how they work, you can write more efficient and effective code.

Do - while loop

The do-while loop in C++ is a control statement that allows you to execute a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

The general syntax of a do-while loop is as follows:

do {
  // code to execute
} while (condition);

The condition can be any Boolean expression. The do-while loop executes the code block at least once, and then it evaluates the condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

Here is an example of a do-while loop:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    do
    {
        cout << "Enter a number: ";
        cin >> num;
        sum += num;
        c++;
    }
    while (c <= 4);
    cout << "sum = " << sum << endl;
    return 0;
}

This code prompts the user to enter four numbers and then prints the sum of those numbers to the console. The program uses a do-while loop to ensure that the user enters at least one number, even if they enter an invalid number the first time.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The do statement begins the do-while loop.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum += num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The while (c <= 4); statement evaluates the condition of the do-while loop. If the c variable is less than or equal to 4, the loop will continue to iterate. Otherwise, the loop will terminate.
  8. If the condition of the loop is true, the code block inside the loop is executed.
  9. Steps 3-7 are repeated until the condition of the loop is false.
  10. After the loop has terminated, the program prints the message “sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
sum = 100

Do-while loops can be used to solve a variety of problems, such as:

  • Validating user input
  • Checking for a certain condition to be met
  • Performing a task a certain number of times

The differences between while loop and do – while loop:

Feature While loop Do-while loop
Condition is checked Before the code block is executed. After the code block is executed.
Guarantee of execution The code block is not guaranteed to be executed at least once. The code block is guaranteed to be executed at least once.

Table explanation

  • While loop: The while loop checks the condition before the code block is executed. If the condition is true, the code block is executed. The code block is executed repeatedly until the condition evaluates to false.
  • Do-while loop: The do-while loop checks the condition after the code block is executed. The code block is executed at least once, regardless of the value of the condition. The code block is executed repeatedly until the condition evaluates to false.

JAVA

Java is a high-level, versatile, and widely-used programming language known for its portability and flexibility. Originally developed by Sun Microsystems and now maintained by Oracle Corporation, Java has a vast ecosystem of libraries and tools that make it a popular choice for various software applications, from web development to mobile apps and enterprise-level systems. Java is appreciated for its ability to run on multiple platforms, its strong security features, and its support for object-oriented programming. It’s a key technology for building dynamic websites, interactive web applications, and mobile apps, making it a vital tool in the world of software development.

Introduction

Java Programming Language

Java is a class-based, object-oriented programming language. It is widely used for developing various types of applications, ranging from simple desktop utilities to complex enterprise-level systems.

Java is available for most operating systems (Write once run anywhere).

Applications of Java with Real-world Examples

  • Applications for Mobiles.
  • Desktop GUI Applications.
  • Web Applications.
  • Gaming Applications.
  • Enterprise Applications.
  • Security.
  • Scientific Applications.
  • Embedded Systems.
  • Big Data Technologies.
  • Distributed Applications.
  • Cloud-based Applications.
  • Web servers and Application servers.
  • Software Tools.

Why do we need to learn programming languages?

There are many reasons why learning a programming language like Java can be valuable, even if you don’t plan to become a professional programmer. Here are just a few:

  • Directly shape the digital landscape: Java is used to build countless websites and mobile apps, from your favorite social media platforms to online banking tools. Learning Java empowers you to be more than just a user; you can become a creator, shaping the digital experiences of others.
  • Boosts problem-solving and critical thinking: Programming helps you develop logical thinking skills and the ability to break down complex problems into smaller, solvable steps. This translates well to other areas of life, from tackling schoolwork to making everyday decisions.
  • Opens career doors: While not essential for every job, programming skills are increasingly sought-after across various industries. Even basic knowledge can give you an edge in many fields, from marketing and finance to data science and education.
  • It’s simply fun and rewarding! There’s a unique satisfaction in seeing your code come to life and create something functional or even beautiful. The learning process itself can be challenging and rewarding, fostering a sense of accomplishment and growth.

We also need to know how to communicate with computers, and to do so we have something called binary system which represents data and instructions using only two symbols: 0 and 1. This system is the foundation of digital computing because electronic devices, such as computers and microprocessors, interpret and process information in binary format.

As a programmer, you write source code to implement specific functions, such as generating text. This source code is written using a specific syntax. For example, in Java, you might write System.out.print(“Java”). This line of code is understandable to humans and is considered a high-level language representation.

However, before the machine can understand and execute this code, it must undergo several steps to translate it into a form it can process. Firstly, the code is passed through a Java compiler (javac), which checks the syntax and transforms the source code into bytecode. Bytecode is a low-level representation of the code that is platform-independent and can be executed by any system with a Java Virtual Machine (JVM).

Next, the bytecode is interpreted by the JVM, which acts as an interpreter. The JVM translates the bytecode into machine code instructions that the underlying operating system can understand and execute. This process allows Java programs to run on various operating systems without modification, making it a key feature of the Java language.

The Java Programming Language Platforms

  • Java Platform, Standard Edition (Java SE)
    – Desktop applications.
  • Java Platform, Enterprise Edition (Java EE)
    – Web applications, Server applications.
  • Java Platform, Micro Edition (Java ME)
    – Mobile applications, Gaming applications.
  • Java FX
    – Platform for desktop, mobile and embedded systems. Built on Java and fully featured toolkit for developing rich client applications.

Installing the Java Development Tools

Download Java Development Kit

To download Java Development Kit (JDK) for Java programming, follow these steps:

  1. Open your web browser and search for “download JDK for Java” on Google. Visit the official Oracle website because Java is owned by Oracle. You’ll be directed to the Java SE Downloads page.
  2. On the Java SE Downloads page, choose the JDK version that corresponds to your operating system. Options are typically available for Windows, macOS, and Linux.
  3. Accept the Oracle Technology Network License Agreement for Oracle Java SE to proceed with the download. Read through the terms and conditions and accept them if you agree.
  4. Click on the download link to start downloading the JDK installer file. The file format will be .exe for Windows, .dmg for macOS, and .tar.gz for Linux.
  5. Once the download is complete, locate the downloaded installer file and run it. Follow the on-screen instructions to install the JDK on your system.

Setting up development environment

Now, to set up your development environment:

  1. Download an Integrated Development Environment (IDE) for Java. Again, perform a Google search for “IDE for Java” and consider downloading Apache NetBeans, which is a user-friendly IDE for Java development. If you don’t want to download the ide you could work with us right now with an online compiler and we recommend ideone.com.
  2. Search for “download NetBeans for Java” on Google. Look for the Apache NetBeans release and download it.
  3. Once the download is complete, you can find the downloaded NetBeans IDE on your device. Navigate to the “Start” menu and click on it to open the NetBeans IDE.
  4. To start your first project in NetBeans, click on “File” > “New Project” > “Java” > “Java Application”. Choose a name for your project (e.g., “FirstProject”) and select your desired location. Click “Finish” to create the project.
  5. In the project window, navigate to the “Source Packages” folder. Right-click on the folder’s content and select “New” > “Java Class”. Name the class using capital letters for each word with no spaces (e.g., “NewClass”). Make sure the class name matches the name of the Java file. Click “Finish” to create the class.

By following these steps, you’ll have successfully downloaded and installed the JDK for Java development, set up the Apache NetBeans IDE, and created your first Java project. You’re now ready to start coding in Java!

Syntax Rules

Here are the rules of Java syntax:

  1. Reserved Words: Certain words in Java are reserved for specific purposes and cannot be used as identifiers (e.g., class, public, static). These words are known as reserved words or keywords and are highlighted in blue.
  2. Code Blocks: All code blocks in Java must be enclosed within curly brackets {}. This includes class definitions, method definitions, loops, and conditional statements.
  3. Main Method: The starting point of a Java program is the main method. It must be declared as public static void main(String[] args) and should always be written as shown below:
    public static void main(String[] args) {
        // Code goes here
    }
    
  4. Semicolons: Semicolons (;) are used to terminate statements in Java. Every statement must end with a semicolon.
  5. Example Program:
    public class MyFirstProgram {
        public static void main(String[] args) {
            System.out.print("Hello");
        }
    }
    

     

  6. The System.out.print() method is a function in Java that is used to display output to the console. Here’s a breakdown of its components:
    – System: System is a class in Java’s java.lang package. It provides access to the standard input, output, and error streams of the system.
    – out: out is a static member of the System class. It represents the standard output stream, which is typically the console or terminal where you see text output when running a Java program.
    – print(): print() is a method of the out object. It is used to display text or other data on the standard output stream without advancing to the next line. Whatever is passed as an argument to the print() method will be displayed on the console.
    For example:

    System.out.print("Hello");
    

    This line of code will display “Hello” on the console.

  7. Case Sensitivity: Java is case-sensitive, meaning that uppercase and lowercase letters are treated as distinct. For example, “hello” and “Hello” are considered different identifiers.

Types of Errors

In Java, errors can generally be categorized into three main types:

  1. Syntax Error: Syntax errors occur when the rules of Java syntax are violated. These errors are detected by the compiler during the compilation process. Common syntax errors include misspelled keywords, missing semicolons, and incorrect use of operators. Syntax errors prevent the program from being compiled successfully.
  2. Runtime Error: Runtime errors, also known as exceptions, occur during the execution of a program. These errors occur when unexpected conditions or situations arise while the program is running. Common examples include dividing by zero, accessing an array element out of bounds, and attempting to use a null object reference. Runtime errors cause the program to terminate abruptly unless they are handled using exception handling mechanisms such as try-catch blocks.
  3. Logical Error: Logical errors occur when the program does not produce the expected output due to incorrect logic or algorithmic errors in the code. Unlike syntax errors and runtime errors, logical errors do not cause the program to terminate or produce error messages. Instead, they result in incorrect behavior or output. Debugging logical errors often involves careful analysis of the code’s logic and algorithm to identify and fix the underlying issue.

Escape Sequences and Comments

Comments

In Java, comments are non-executable statements that are ignored by the compiler. They are used to provide explanations, documentation, and annotations within the code. There are three types of comments in Java:

  1. Single-line comments: Single-line comments begin with two forward slashes (//). Everything after // on the same line is considered a comment and is ignored by the compiler. Single-line comments are typically used for short explanations or comments on a single line of code.
    Example:

    // This is a single-line comment
    
  2. Multi-line comments: Multi-line comments, also known as block comments, are enclosed between /* and */. Everything between these symbols, including newlines, is considered a comment. Multi-line comments are often used for longer explanations or comments that span multiple lines of code.
    Example:

    /* This is a
       multi-line comment */
    
  3. Javadoc comments: Javadoc comments are a special type of comment used to generate documentation. They start with /** and end with */. Javadoc comments are used to describe classes, methods, and fields, and can include special tags to provide additional information such as parameters, return values, and exceptions.
    Example:

    /**
     * This is a Javadoc comment for the MyClass class.
     */
    public class MyClass {
        /**
         * This is a Javadoc comment for the myMethod method.
         * @param x This is a parameter of the method.
         * @return This method returns a value.
         */
        public int myMethod(int x) {
            return x * x;
        }
    }
    

Escape Sequences:

In Java, escape sequences are special character combinations used to represent characters that are difficult or impossible to represent directly in a string literal. Escape sequences are preceded by a backslash () character. Here are some common escape sequences used in Java:

  1. \n: Represents a newline character. When used within a string literal, it moves the cursor to the beginning of the next line.
  2. \t: Represents a tab character. When used within a string literal, it inserts a horizontal tab.
  3. \’: Represents a single quote character. Used to include single quote within a string literal.
  4. \”: Represents a double quote character. Used to include double quotes within a string literal.
  5. \\: Represents a backslash character. Used to include a backslash within a string literal.
  6. \r: Represents a carriage return character.
  7. \b: Represents a backspace character.
  8. \f: Represents a form feed character.

Example:

public class EscapeSequencesExample {
    public static void main(String[] args) {
        // Newline (\n) escape sequence
        System.out.println("Hello\nWorld"); // Output: Hello
                                            //         World
        
        // Tab (\t) escape sequence
        System.out.println("Java\tProgramming"); // Output: Java    Programming
        
        // Double quote (\") escape sequence
        System.out.println("She said, \"Hello!\""); // Output: She said, "Hello!"
        
        // Backslash (\\) escape sequence
        System.out.println("C:\\Users\\John\\Documents"); // Output: C:\Users\John\Documents
        
        // Carriage return (\r) escape sequence
        System.out.println("Overwritten text\r123"); // Output: 123written text
        
        // Backspace (\b) escape sequence
        System.out.println("Back\bspace"); // Output: Backspace
        
        // Form feed (\f) escape sequence
        System.out.println("Hello\fWorld"); // Output: Hello
                                             //         World

    }
}

 

Data Types

Naming Variables

In Java, variable names must adhere to certain standard rules to ensure clarity, readability, and compatibility with the language syntax. Here are the standard rules for naming variables in Java:

  1. Variable Name Length: Variable names can be of any length. However, it’s recommended to use meaningful and descriptive names while keeping them concise and readable.
  2. Valid Characters: Variable names can consist of letters (both uppercase and lowercase), digits, the underscore character (_), and the dollar sign ($). They must start with a letter, underscore, or dollar sign.
  3. Reserved Words: Variable names cannot be the same as Java keywords or reserved words. For example, you cannot name a variable “class” or “int” as they are reserved words in Java.
  4. Case Sensitivity: Java is case-sensitive, meaning uppercase and lowercase letters are treated as different characters. Therefore, “myVar” and “myvar” would be considered as two different variables.
  5. CamelCase Convention: It’s a common convention in Java to use CamelCase for naming variables. CamelCase involves writing compound words or phrases such that each word or abbreviation begins with a capital letter, with no spaces or punctuation between them. For example: myVariableName, totalAmount, studentAge.
  6. Meaningful Names: Variable names should be descriptive and convey the purpose or meaning of the variable. Avoid using single-letter variable names (except for loop counters) or overly cryptic abbreviations.
  7. Start with Lowercase: It’s a convention in Java to start variable names with a lowercase letter, except for constants, which are typically written in all uppercase.
  8. Special Characters: In addition to letters, digits, and underscore, you can use the dollar sign ($) as a special character in variable names. Avoid using other special characters like @, %, etc.

By adhering to these standard rules, you can create clear, concise, and meaningful variable names in Java code, promoting readability and maintainability.

Data Types

In Java, data types specify the type of data that can be stored in a variable. Java has two categories of data types: primitive data types and reference data types.

Primitive Data Types:

Primitive data types are the most basic data types in Java. They represent single values and are predefined by the language. There are eight primitive data types in Java:

  1. byte: Byte data type is an 8-bit signed two’s complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
  2. short: Short data type is a 16-bit signed two’s complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive).
  3. int: Int data type is a 32-bit signed two’s complement integer. It has a minimum value of -2^31 and a maximum value of 2^31-1.
  4. long: Long data type is a 64-bit signed two’s complement integer. It has a minimum value of -2^63 and a maximum value of 2^63-1.
  5. float: Float data type is a single-precision 32-bit IEEE 754 floating-point. It should never be used for precise values, such as currency.
  6. double: Double data type is a double-precision 64-bit IEEE 754 floating-point. It is used for decimal values that require more precision.
  7. boolean: Boolean data type represents one bit of information. It has only two possible values: true and false.
  8. char: Char data type is a single 16-bit Unicode character. It has a minimum value of ‘\u0000’ (0) and a maximum value of ‘\uffff’ (65,535 inclusive).

Example:

byte age = 25;
short distance = 10000;
int population = 1500000;
long nationalDebt = 20202020202020L; // Use 'L' suffix for long literals
float temperature = 32.5f; // Use 'f' suffix for float literals
double pi = 3.14159265359;
boolean isJavaFun = true;
char grade = 'A';

These primitive data types are the building blocks of Java programs, allowing developers to store and manipulate different types of data efficiently. Understanding their characteristics and appropriate usage is essential for writing effective Java code.

Note: There is srt which refers to string, but it is considered as an object data type.

Priorities & Calculations in C++

C++ has a set of operator precedence rules that determine the order in which expressions are evaluated. Operators with higher precedence are evaluated before operators with lower precedence.

Here is a table of the operator precedence rules in C++:

Operator Group Operators
Parentheses ()[]{}
Unary operators +-!~*&++--sizeofcasttype-name
Multiplication, division, and modulus */%
Addition and subtraction +-
Bitwise AND &
Bitwise OR |
Bitwise XOR ^
Equality and inequality ==!=
Less than, less than or equal to, greater than, greater than or equal to <<=>>=
Logical AND &&
Logical OR ||
Assignment =+=-=*=/=%=&=, `
Conditional operator ? :
Comma ,

When evaluating an expression, operators with the highest precedence are evaluated first, followed by operators with lower precedence.

Here are some examples of how operator precedence works in C++:

// Evaluates to 13.
int x = 5 * 2 + 3;

// Evaluates to 11.
int y = 5 + 2 * 3;

// Evaluates to true.
bool z = 5 < 10 && 10 > 5;

// Evaluates to false.
bool w = 5 > 10 || 10 < 5;

It is important to be aware of operator precedence when writing C++ code. Otherwise, you may get unexpected results.

Here is another example of how operator precedence can be used to control the order of evaluation:

// Evaluates to 16.
int a = (5 + 3) * 2;

// Evaluates to 11.
int b = 5 + (3 * 2);

In the first expression, the addition operator (+) has higher precedence than the multiplication operator (*). Therefore, the addition operation is evaluated first, and then the multiplication operation is evaluated.

In the second expression, the multiplication operation has higher precedence than the addition operation. Therefore, the multiplication operation is evaluated first, and then the addition operation is evaluated.

By understanding operator precedence, you can write more concise and efficient C++ code.

For loop

The for loop in C++ is a control statement that allows you to execute a block of code repeatedly a certain number of times. The general syntax of a for loop is as follows:

for (initialization; condition; increment) {
  // code to execute
}

The initialization statement is executed once, before the for loop starts. The condition statement is evaluated before each iteration of the loop. If the condition is true, the code block inside the loop is executed. The increment statement is executed after each iteration of the loop.

Here is an example of a for loop:

#include <iostream>

using namespace std;

int main()
{
    
    for (int c = 0; c < 10; c++)
    {
        cout << c << endl;
    }
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the c variable to 0.
  2. The condition statement checks if the c variable is less than 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the c variable to the console.
  4. The increment statement increments the c variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

0
1
2
3
4
5
6
7
8
9

Here is another example that prompts the user to enter 10 marks and then prints the average of those marks to the console:

#include <iostream>

using namespace std;

int main()
{
    int m = 0, sum = 0;
    for (int i = 1; i <= 10; i++)
    {
        cout << "Enter your marks:";
        cin >> m;
        sum = sum + m;
    }
    cout << "the avg = " << ((double)sum / 10) << endl;
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 1.
  2. The condition statement checks if the i variable is less than or equal to 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prompts the user to enter their marks and stores the value in the m variable. The code block also adds the value of the m variable to the sum variable.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

After the for loop has terminated, the program prints the average of the marks to the console. The average is calculated by dividing the sum of the marks by the number of marks.

You used the (double) cast in the expression ((double)sum / 10) to ensure that the result of the division operation is a floating-point number. This is important because the sum variable is an integer variable, and the division of two integers results in an integer. If you did not use the (double) cast, the program would print the integer result of the division operation to the console, which may not be accurate.

Here is an example of the output of this program:

Enter your marks: 10
Enter your marks: 20
Enter your marks: 30
Enter your marks: 40
Enter your marks: 50
Enter your marks: 60
Enter your marks: 70
Enter your marks: 80
Enter your marks: 90
Enter your marks: 100
the avg = 55.000000

This code prints the numbers from 10 to 50 to the console, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i <= 50; i++)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is less than or equal to 50. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Why is size_t used as the loop counter?

The size_t type is used as the loop counter because it is the type that is returned by the sizeof operator. This ensures that the loop counter can be used to iterate over any type of data, including arrays and objects.

This code prints the numbers from 10 to 1 to the console, in reverse order, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i >= 1; i--)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is greater than or equal to 1. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The decrement statement decrements the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 9 8 7 6 5 4 3 2 1

OOP in JAVA

Object-Oriented Programming (OOP) is a fundamental programming paradigm used extensively in Java. In OOP, the core concept is organizing code into “objects,” which are instances of classes representing real-world entities, concepts, or data structures.

Introduction

Object-oriented programming

Object-oriented programming is a methodology or paradigm to design a program using classes and objects. It has many advantages like:

  • Reusability.
  • Readability.
  • Performance.
  • Space.

Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects. Java is a powerful and widely-used programming language that fully supports OOP principles.

Other languages that support OOP: Python, C++, Visual Basic, NET and Ruby.

There are other methodologies like:

  • Procedural programming that is used by C, Pascal, COBOL, FORTRAN, Java, Python, C++ ..etc.
  • Event-driven that is used by C#, Visual Basic, Visual C++ and Java.

Objects are fundamental building blocks in object-oriented programming (OOP) and play a crucial role in the design and implementation of systems. To illustrate this concept, let’s consider the example of designing a store system.

When we think about building a store system, the first thing that comes to mind is the objects involved. In this case, we can identify three main objects: products, customers, and payment methods.

Products: Products represent the items that the store sells. These could be anything from groceries to electronics or clothing. Each product in the store is characterized by its unique attributes such as name, price, quantity, and category. In OOP, products can be represented as objects with properties and behaviors. For example, we could have a Product class with attributes like name, price, and quantity, and methods to update product information or check availability.

Customers: Customers are individuals or entities who visit the store to purchase products. They interact with the store by browsing products, selecting items for purchase, and completing transactions. In OOP, customers can be modeled as objects with attributes such as name, address, contact information, and purchase history. We could have a Customer class with methods to place orders, view order history, or update personal details.

Payment Method: Payment methods are mechanisms used by customers to pay for their purchases. These could include cash, credit/debit cards, mobile wallets, or online payment gateways. Each payment method has its own set of rules and procedures for processing transactions. In OOP, payment methods can be represented as objects with properties and behaviors related to processing payments. We could define different payment method classes with methods to authorize payments, handle refunds, or generate transaction receipts.

By identifying these objects and their relationships, we can design a cohesive and modular store system that encapsulates the functionality of managing products, serving customers, and processing payments. Each object in the system encapsulates its own state and behavior, promoting encapsulation, modularity, and code reuse, which are key principles of object-oriented programming.

Objects

Objects in object-oriented programming (OOP) are composed of two essential members: data (properties, attributes) and operations (methods, functions, behaviors). These elements encapsulate the state and behavior of the object, respectively, and work together to represent real-world entities within a software system.

Let’s explore the car example to better understand these concepts:

  1. Attributes:
    Name: Represents the brand or manufacturer of the car.
    Max Speed: Indicates the maximum speed the car can achieve.
    Price: Denotes the cost or price of the car.
    Model: Represents the specific model or version of the car.
  2. Operations:
    move(): Represents the action of moving the car. This method may involve starting the engine, accelerating, braking, and steering.
    calculateVehicleAge(): Calculates the age of the car based on its manufacturing year or model year.
  3. Getters and Setters:
    get(): Getter methods retrieve the current value of an attribute.
    set(): Setter methods modify or update the value of an attribute.

For example, in the car class, we may have getter and setter methods for each attribute, such as getName() and setName() for the name attribute, getMaxSpeed() and setMaxSpeed() for the max speed attribute, and so on. These methods allow external code to access and modify the state of the car object in a controlled manner, promoting encapsulation and data integrity.

Additionally, the class diagram is a graphical representation of the structure and relationships of classes in a software system. It visually depicts the classes, their attributes, methods, and associations with other classes. Class diagrams provide a high-level overview of the system’s architecture and help developers understand the relationships between different components.

Classes

In object-oriented programming (OOP), a class is a blueprint or template that defines the structure and behavior of objects. It serves as a blueprint for creating objects with similar characteristics and functionalities. Classes encapsulate data (attributes) and operations (methods) into a single unit, providing a modular and reusable way to model real-world entities within a software system.

 

Classes and Objects

Creating a Class in Java using NetBeans:

Classes are like blueprints that define the structure and behavior of objects in Java. Think of them as templates for building specific objects with unique properties and abilities.

In Apache NetBeans, follow these steps to create a new class:

Project Setup:

  1. Go to File > New Project > Java Application.
  2. Name your project (e.g., JavaOOP) and click Finish.

Package Creation:

  1. Navigate to the Source Packages section.
  2. Click the + sign and choose New > Java Package.
  3. Name your package (e.g., com.mycompany.javaoop) and click Finish.

Class Creation:

  1. Right-click on the package you created.
  2. Select New > Java Class.
  3. Name your class (e.g., Main) and click Finish.

Code:

package com.mycompany.javaoop;

public class Main {
    public static void main(String[] args) {
        System.out.println("JAVA");
    }
}

Explanation of the Code:

– package com.mycompany.javaoop;: This line specifies the package where your Main class belongs. Organizing classes into packages helps maintain code structure and avoid naming conflicts.
– public class Main: This declares a public class named Main. Public classes can be accessed from other parts of your project.
– public static void main(String[] args): This is the main method, the entry point where your program execution begins.
– System.out.println(“JAVA”);: This line prints the string “JAVA” to the console.

Troubleshooting and Tips:

<No main classes found> Error: If you encounter this error, ensure you’ve set the Main Class field in your project’s Run configuration to com.mycompany.javaoop.Main.

Here’s how to address the “No main classes found” error in NetBeans:

  1. Right-click on the project name (in this case, “JavaOOP”) in the Projects window.
  2. Select Properties.
  3. Go to the Run category.
  4. In the Main Class field, enter the fully qualified name of your main class, including the package name. For example, if your class is named “Main” and it’s in the package “com.mycompany.javaoop”, you would enter com.mycompany.javaoop.Main.
  5. Click OK to save the changes.

Now try running your code again. It should execute without the “No main classes found” error.

Creating Classes and Objects:

Separate Files for Separate Classes: Each class in Java needs its own file, distinct from the Main class. This promotes organization and modularity in your code.

Creating the Car Class:

  1. Right-click on the package where you want to create the new class (e.g., com.mycompany.javaoop).
  2. Select New > Java Class.
  3. Name the class Car (capitalizing the first letter is a Java naming convention).
  4. Click Finish. This generates a new file named Car.java within your package.

Naming Convention for Classes:

  • Always start class names with a capital letter.
  • Use descriptive names that reflect the class’s purpose (e.g., Car, Person, Account).
  • This convention makes your code more readable and easier to understand.

Example 1:

class Car {
    String name;
    int maxSpeed;
    float price;
    int model;
}

Class Declaration:

  • class Car – This line declares a new class named Car.

Attributes:

  • String name; – This defines an attribute named name of type String. It will store the name of the car object.
  • int maxSpeed; – This defines an attribute named maxSpeed of type int. It will store the maximum speed of the car object in kilometers per hour.
  • float price; – This defines an attribute named price of type float. It will store the price of the car object in a floating-point format.
  • int model; – This defines an attribute named model of type int. It will store the model year of the car object.

Now we will create our instances for Car class in the Main class, because it is the entry point of the program where execution starts.

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.maxSpeed = 210;
        Car c2 = new Car();
        c2.name = "Kia";
        System.out.println(c1.name);
        System.out.println(c1.maxSpeed);
        System.out.println(c2.name);
    }
}

This code still uses the Car class with attributes like name, maxSpeed, price, and model.
Main Class:

  • public static void main(String args[]): This line remains the entry point of your program.
  • Car c1 = new Car();: This line creates a new instance of the Car class and assigns it to the variable c1.
  • c1.name = “Tesla”;: This line sets the name attribute of the c1 object to “Tesla”.
  • c1.maxSpeed = 210;: This line sets the maxSpeed attribute of the c1 object to 210 kilometers per hour.
  • Car c2 = new Car();: This line creates another new instance of the Car class and assigns it to the variable c2.
  • c2.name = “Kia”;: This line sets the name attribute of the c2 object to “Kia”.
  • System.out.println(c1.name);: This line prints the value of the name attribute of the c1 object to the console, which should output “Tesla”.
  • System.out.println(c1.maxSpeed);: This line prints the value of the maxSpeed attribute of the c1 object to the console, which should output “210”.
  • System.out.println(c2.name);: This line prints the value of the name attribute of the c2 object to the console, which should output “Kia”.

Example 2:

Car Class:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) {
        name = n;
    }
    String getName() {
        return name;
    }
}
  • It has four attributes: name, maxSpeed, price, and model. These attributes are not shown in this example, but they could store information about a car’s name, maximum speed, price, and model year.
  • It also has two methods:
    – setName(String n): This method takes a string argument n and sets the car’s name attribute to that value.
    – getName(): This method returns the current value of the car’s name attribute as a string.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setName("KIA");
        System.out.println(c1.getName());
    }
}
  • It creates a new instance of the Car class and assigns it to the variable c1.
  • It sets the car’s name attribute to “Tesla” using the direct assignment (c1.name = “Tesla”).
  • Then, it overwrites the name by calling the setName method with the argument “KIA”. This method changes the internal name attribute of the c1 object.
  • Finally, it prints the car’s name using the getName method, which retrieves the current value (“KIA”) and prints it to the console.

Example 3:

Class Car:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) { // Setters/ Mutators
        name = n;
    }
    String getName() {       // Getters/ Accessors
        return name;
    }
    void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    int getModel() {
        return model;
    }
}
  • Attributes: It still has name, maxSpeed, price, and model.
  • Methods:
    – Setters: These methods allow setting specific attribute values.
    – setName(String n): Sets the name attribute.
    – setModel(int m): Sets the model attribute with a validation check, only accepting years 2015 or later.
    – Getters: These methods retrieve specific attribute values.
    – getName(): Returns the name attribute value.
    – getModel(): Returns the model attribute value.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setModel(2021);
        System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object.
  • c1.name = “Tesla”;: Sets the name attribute of c1 using the default behavior (no setter needed).
  • c1.setModel(2021);: Sets the model attribute of c1 using the setter. Since 2021 is valid, it updates the model.
  • System.out.println(c1.getModel());: Prints the model attribute of c1, which should output “2021”.

Access Level Modifiers in Java

(Controlling Visibility and Encapsulation)

Access level modifiers are fundamental constructs in Java that determine the visibility and accessibility of class members (fields, methods, constructors). They play a crucial role in promoting encapsulation, a core principle of object-oriented programming that ensures data protection and modularity.

Key Concepts:

  • Visibility: Refers to whether a class member is directly visible and usable from other parts of your code.
  • Accessibility: Refers to the ability to directly access a class member without using special mechanisms.

Types of Access Level Modifiers:

  1. Public:
    Members declared public are visible and accessible from anywhere in your program.
    Use this modifier judiciously for elements that need to be widely used, but be cautious not to expose implementation details unnecessarily.
  2. Private:
    Members declared private are only visible and accessible within the class where they are defined.
    This promotes encapsulation by restricting direct access to internal data, encouraging the use of public methods to control interactions with the class.
  3. Protected:
    Members declared protected are visible and accessible within the class where they are defined, its subclasses in the same package, and subclasses in different packages (but not directly from other classes in different packages).
    This modifier is useful for creating a base class (superclass) with protected members that can be accessed and potentially overridden by its subclasses, promoting code reuse and inheritance.
  4. Default (Package-Private):
    Members declared without any access modifier are visible and accessible within the same package (the package containing the class definition).
    This provides a balance between visibility and access control within a package.

Example 4:

This code effectively demonstrates fundamental object-oriented concepts like encapsulation, access modifiers, and object interaction in Java. It provides a solid foundation for building more complex and robust Java applications.

Car Class:

public class Car { 
    private String name; 
    private int maxSpeed; 
    private float price; 
    private int model;
    
    public void setName(String n) { // Setters/ Mutators
        name = n;
    }
    public String getName() {       // Getters/ Accessors
        return name;
    }
    public void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    public int getModel() {
        return model;
    }
}
  • Attributes:
    – name: Private String storing the car’s name.
    – maxSpeed: Private int storing the car’s maximum speed.
    – price: Private float storing the car’s price.
    – model: Private int storing the car’s model year.
  • Methods:
    – setName(String n): Public setter to set the car’s name.
    – getName(): Public getter to retrieve the car’s name.
    – setModel(int m): Public setter to set the car’s model year, including validation for years 2015 or later.
    – getModel(): Public getter to retrieve the car’s model year.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
    c1.setModel(2021);
    System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object named c1.
  • c1.setModel(2021);: Attempts to set the model of c1 to 2021. This succeeds because 2021 is a valid year.
  • System.out.println(c1.getModel());: Prints the model of c1 to the console, which outputs “2021”.

Key Points:

  • Encapsulation: The Car class encapsulates its data using private attributes, ensuring controlled access through public methods.
  • Data Validation: The setModel method includes validation to prevent invalid model years, promoting data integrity.
  • Object Interaction: The Main class demonstrates how to create a Car object and interact with it using its public methods.
  • Setters and Getters: These methods provide a controlled way to modify and retrieve object attributes, upholding encapsulation principles.

Data Hiding

Data Hiding is a software development technique specifically used in object-oriented programming (OOP). Data hiding ensures exclusive data access to class members and protects object integrity by preventing unintended or intended changes.

Why do we use this technique?
Because we could have many object that will connect through messages and use each other methods.

Encapsulation
Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.

To achieve encapsulation in Java:

  • Declare the variables of a class as private.
  • Provide public setter and getter methods to modify and view the variables values.

Questions and Exercises

Build a class to find the area and circumference of a circle

Circle class:

package com.mycompany.javaoop;

public class Circle {
    private double radius;
    private String color;
    
    public double getRadius() {
        return radius;
    }
    
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    public double getCircumference() {
        return Math.PI * 2 * radius;
    }
    
    public String toString() {
        return "Circle{" + "radius=" + radius + ", color=" + color + "}";
    }
}

Attributes:

  • radius: Private double attribute to store the circle’s radius.
  • color: Private String attribute to store the circle’s color (optional, for additional information).

Methods:

– Getters and Setters:

  • getRadius(): Returns the current value of the radius attribute.
  • setRadius(double radius): Sets the value of the radius attribute, potentially with validation (not included in this example).
  • getColor(): Returns the current value of the color attribute (if present).
  • setColor(String color): Sets the value of the color attribute (if present).

– Area and Circumference:

  • getArea(): Calculates and returns the area of the circle using Math.PI * radius * radius.
  • getCircumference(): Calculates and returns the circumference of the circle using Math.PI * 2 * radius.
  • toString(): Overrides the default toString() method to provide a more descriptive representation of the Circle object, including its radius and color (if present).

Main Class:

package com.mycompany.javaoop;

public class Main
{
    public static void main(String args[]) {
        Circle c1 = new Circle(), c2 = new Circle();
        c1.setRadius(3.0);
        c1.setColor("Black");
        System.out.println("c1 area = " + c1.getArea());
        System.out.println(c1.toString());
        
        c2.setRadius(2.0);
        c2.setColor("Blaue");
        System.out.println("c2 Circumference = " + c2.getCircumference());
    }
}
  • Creates two Circle objects: c1 and c2.
  • Sets the radius and color (if applicable) for each object.
  • Calculates and prints the area of c1 and the circumference of c2.
  • Optionally, you could call c1.toString() and c2.toString() to print their complete representations.

Build a simple banking system

Account class:

package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}

Attributes:

  • accountNo: Private int stores the account number.
  • name: Private String stores the account holder’s name.
  • amount: Private float stores the account balance.

Methods:

  • insert(int a, String n, float amt):
    Initializes an account with the provided account number, name, and initial amount.
  • deposit(float amt):
    Deposits the specified amount into the account.
    Prints a confirmation message with the deposited amount.
  • withdraw(float amt):
    Withdraws the specified amount from the account, but only if there’s sufficient balance.
    Prints a confirmation message if successful, or an “Insufficient Balance” message otherwise.
  • checkBalance():
    Displays the current account balance.
  • toString():
    Overrides the default toString() method to provide a custom string representation of the account, including its account number, name, and balance.

Now complete this code as an exercise by creating the appropriate instances. For further information please watch this video: Questions and Exercises – Classes and Objects

Constructor (No-Arg, Parameterized, Default)

What is a Constructor?

  • It’s a special method in a Java class that’s automatically invoked when a new object of that class is created.
  • Its primary purpose is to initialize the object’s attributes (fields or variables) to appropriate initial values.
  • It ensures objects are created in a valid and consistent state.

Rules for Creating Constructors:

  1. Same Name as Class: The constructor’s name must be exactly the same as the class name.
  2. No Explicit Return Type: Constructors don’t have a return type, not even void.
  3. Cannot Have Modifiers: Constructors cannot be declared as abstract, static, final, or synchronized.

Constructor Types:

  1. No-Arg Constructor: a constructor that does not accept any arguments.
    public class Product {
        private String name;
        private String description;
        private float price;
        private int quantity;
        private float discount;
    
        public Product() {
            this.name = "No name";
            this.description = "No description";
            this.price = 0.0f;
            this.quantity = 0;
            this.discount = 0;
        }
    }
  2. Parameterized Constructor: a constructor that accepts arguments.
    public Product(String n, String d, float p, int q, float dis) {
            this.name = n;
            this.description = d;
            this.price = p;
            this.quantity = q;
            this.discount = dis;
        }
  3. Default Constructor: A constructor that is automatically created by Java compiler if it is not explicitly defined.

Constructor Chaining

Constructor Chaining: When a constructor calls another constructor of the same class then it is called constructor chaining.

Code:

Product class:

public class Product {
    private String name;
    private String description;
    private float price;
    private int quantity;
    private float discount;
    private String color;
    
    public Product() {
        this.name = "No name";
        this.description = "No description";
        this.price = 0.0f;
        this.quantity = 0;
        this.discount = 0;
    }
    
    public Product(String n, String d, float p, int q, float dis) {
        this.name = n;
        this.description = d;
        this.price = p;
        this.quantity = q;
        this.discount = dis;
        System.out.println("constructor: 5");
    }
    
    public Product(String n, String d, float p, int q, float dis, String c) {
        this (n,d,p,q,dis);
        this.color = c;
        System.out.println("constructor: 6");
    }
    
    public void display() {
        System.out.println("Name = " + name);
        System.out.println("description = " + description);
        System.out.println("Price = " + price);
        System.out.println("Quantity = " + quantity);
        System.out.println("Discount = " + Discount);
    }
}

Attributes:

  • name: String representing the product name.
  • description: String describing the product.
  • price: float storing the product price.
  • quantity: int representing the product quantity.
  • discount: float representing the discount percentage.
  • color: String (optional) for the product color (added in the third constructor).

Constructors:

  • Product() (Default Constructor): Initializes all attributes with default values (“No name”, “No description”, etc.).
  • Product(String n, String d, float p, int q, float dis): Parameterized constructor taking arguments for name, description, price, quantity, and discount. Prints “constructor: 5” upon invocation.
  • Product(String n, String d, float p, int q, float dis, String c): Parameterized constructor taking arguments for all attributes, including color. Internally calls the second constructor (“constructor: 5”) and then sets the color. Prints “constructor: 6” upon invocation.
  • display() method: Prints the product information in a user-friendly format.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Product p1 = new Product("Camera", "Auto focus", 99, 10, 5, "red");
        Product p2 = new Product();
        p.display();

    }
}

Creates two Product objects:

  • p1 using the third constructor, providing values for all attributes.
  • p2 using the default constructor (no arguments provided).

Attempts to call the display() method on the incorrectly referenced variable p (should be p2) to display the default values.

Questions and Exercises

Build a class to find the area and circumference of a circle

Circle class:

package com.mycompany.javaoop;

public class Circle {
    private double radius;
    private String color;
    
    public double getRadius() {
        return radius;
    }
    
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    public double getCircumference() {
        return Math.PI * 2 * radius;
    }
    
    public String toString() {
        return "Circle{" + "radius=" + radius + ", color=" + color + "}";
    }
}

Attributes:

  • radius: Private double attribute to store the circle’s radius.
  • color: Private String attribute to store the circle’s color (optional, for additional information).

Methods:

– Getters and Setters:

  • getRadius(): Returns the current value of the radius attribute.
  • setRadius(double radius): Sets the value of the radius attribute, potentially with validation (not included in this example).
  • getColor(): Returns the current value of the color attribute (if present).
  • setColor(String color): Sets the value of the color attribute (if present).

– Area and Circumference:

  • getArea(): Calculates and returns the area of the circle using Math.PI * radius * radius.
  • getCircumference(): Calculates and returns the circumference of the circle using Math.PI * 2 * radius.
  • toString(): Overrides the default toString() method to provide a more descriptive representation of the Circle object, including its radius and color (if present).

Main Class:

package com.mycompany.javaoop;

public class Main
{
    public static void main(String args[]) {
        Circle c1 = new Circle(), c2 = new Circle();
        c1.setRadius(3.0);
        c1.setColor("Black");
        System.out.println("c1 area = " + c1.getArea());
        System.out.println(c1.toString());
        
        c2.setRadius(2.0);
        c2.setColor("Blaue");
        System.out.println("c2 Circumference = " + c2.getCircumference());
    }
}
  • Creates two Circle objects: c1 and c2.
  • Sets the radius and color (if applicable) for each object.
  • Calculates and prints the area of c1 and the circumference of c2.
  • Optionally, you could call c1.toString() and c2.toString() to print their complete representations.

Build a simple banking system

Account class:

package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}

Attributes:

  • accountNo: Private int stores the account number.
  • name: Private String stores the account holder’s name.
  • amount: Private float stores the account balance.

Methods:

  • insert(int a, String n, float amt):
    Initializes an account with the provided account number, name, and initial amount.
  • deposit(float amt):
    Deposits the specified amount into the account.
    Prints a confirmation message with the deposited amount.
  • withdraw(float amt):
    Withdraws the specified amount from the account, but only if there’s sufficient balance.
    Prints a confirmation message if successful, or an “Insufficient Balance” message otherwise.
  • checkBalance():
    Displays the current account balance.
  • toString():
    Overrides the default toString() method to provide a custom string representation of the account, including its account number, name, and balance.

Now complete this code as an exercise by creating the appropriate instances. For further information please watch this video: Questions and Exercises – Classes and Objects

Basic Arithmetic & Casting

Basic Arithmetic in C++

C++ provides a number of operators for performing basic arithmetic operations. These operators include:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulo (remainder)

These operators can be used to perform arithmetic operations on variables of different data types. For example, the following code performs arithmetic operations on variables of type int and float:

int a = 10;
float b = 3.14159;

// Add two integers.
int c = a + 5;

// Multiply two floats.
float d = b * 2;

// Divide two integers.
float e = a / 2;

// Calculate the remainder of a division operation.
int f = a % 2;

The results of these operations are stored in the corresponding variables.

Casting in C++

Casting is a way to convert a value from one data type to another. This can be useful when you need to perform arithmetic operations on values of different data types.

There are two types of casting in C++:

  • Implicit casting: Implicit casting occurs when the compiler automatically converts a value from one data type to another. For example, the following code implicitly converts the value of the variable a from type int to type float before performing the multiplication operation:

 

int a = 10;
float b = 3.14159;

// Multiply an int and a float.
float c = a * b;
  • Explicit casting: Explicit casting is when the programmer explicitly converts a value from one data type to another. This can be done using the cast operators (static_castreinterpret_castconst_cast, and dynamic_cast). For example, the following code explicitly converts the value of the variable b from type float to type int before performing the division operation:

 

int a = 10;
float b = 3.14159;

// Divide a float by an int.
int c = static_cast<int>(b) / a;

Explicit casting is often used to prevent errors that can occur when implicitly casting values.

Example

Here is an example of how to use casting in C++:

// Convert a string to an integer.
int a = static_cast<int>("10");

// Convert a floating-point number to a character.
char b = static_cast<char>(3.14159);

// Convert a pointer to an integer to a pointer to a float.
float *c = reinterpret_cast<float*>(pInt);

// Convert a const object to a non-const object.
int *d = const_cast<int*>(pInt);

Casting can be a powerful tool for converting values between different data types. However, it is important to use it carefully to avoid errors.

Prefix and Postfix & Compound assignment

Prefix and postfix operators in C++

Prefix and postfix operators are used to modify the value of a variable. The prefix operator is used before the variable, while the postfix operator is used after the variable.

The following table shows some of the most common prefix and postfix operators in C++:

Operator Prefix Postfix
++ Increments the value of the variable by 1. Increments the value of the variable by 1, and returns the original value.
Decrements the value of the variable by 1. Decrements the value of the variable by 1, and returns the original value.

Example

The following code shows how to use the prefix and postfix operators to increment the value of a variable:

int a = 10;

// Increment the value of a by 1 using the prefix operator.
a++;

// Increment the value of a by 1 using the postfix operator.
int b = a++

// Print the values of a and b.
std::cout << a << " " << b << std::endl;

Output:

12 11

Compound assignment operators in C++

Compound assignment operators combine arithmetic operations with assignment operations. This makes it possible to modify the value of a variable in a single statement.

The following table shows some of the most common compound assignment operators in C++:

Operator Description Example
+= Adds the operand to the left operand x += 5; is equivalent to x = x + 5;
-= Subtracts the operand from the left operand y -= 3; is equivalent to y = y - 3;
*= Multiplies the operand with the left operand z *= 2; is equivalent to z = z * 2;
/= Divides the left operand by the operand a /= 4; is equivalent to a = a / 4;
%= Computes the modulo of the left operand and the operand b %= 7; is equivalent to b = b % 7;
&= Performs a bitwise AND operation on the left operand and the operand c &= 6; is equivalent to c = c & 6;
^= Performs a bitwise XOR operation on the left operand and the operand e ^= 8; is equivalent to e = e ^ 8;
<<= Shifts the left operand left by the number of bits specified by the operand f <<= 3; is equivalent to f = f << 3;
>>= Shifts the left operand right by the number of bits specified by the operand g >>= 2; is equivalent to g = g >> 2;

Example

The following code shows how to use compound assignment operators to modify the value of a variable:

int a = 10;

// Increment the value of a by 1 using the compound assignment operator.
a += 1;

// Print the value of a.
std::cout << a << std::endl;

Output:

11

Compound assignment operators can be a powerful tool for writing concise and efficient C++ code.

Variable Scope (Local vs Global)

Variable scope is a concept in programming that determines where a variable can be accessed from in a program. There are two types of variable scope in C++: local and global.

  • Local variables: Local variables are declared within a function or block of code. They can only be accessed from within the function or block of code in which they are declared.
  • Global variables: Global variables are declared outside of any function or block of code. They can be accessed from anywhere in the program.

Example of local variable scope:

int main() {
  int local_variable = 10;

  // local_variable can only be accessed from within this function.
  std::cout << local_variable << std::endl;

  // This code will cause an error because local_variable is not accessible here.
  std::cout << global_variable << std::endl;

  return 0;
}

Example of global variable scope:

int global_variable = 20;

int main() {
  // global_variable can be accessed from anywhere in the program.
  std::cout << global_variable << std::endl;

  // This code is also valid.
  int local_variable = global_variable;

  return 0;
}

It is important to be aware of variable scope when writing C++ code. Otherwise, you may accidentally access a variable that is not defined or that you are not supposed to access.

Here are some general rules for variable scope in C++:

  • Local variables are scoped to the function or block of code in which they are declared.
  • Global variables are scoped to the entire program.
  • Variables declared in a function can shadow variables declared in the global scope.
  • Variables declared in a block of code can shadow variables declared in the function scope.

By understanding variable scope, you can write more efficient and reliable C++ code.

Selection Statement - if Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

In this section will know more about if statement.

if

The if statement is a conditional statement in C++ that allows you to execute code based on a condition. The general syntax of an if statement is as follows:

if (condition) {
  // code to execute if the condition is true
}

The condition can be any Boolean expression. If the condition evaluates to true, the code block inside the if statement is executed. If the condition evaluates to false, the code block inside the else statement is executed.

Here is an example of an if statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is Positive" << endl;

    return 0;
}

Output:

  • Case 1: if you entered a positive digit like 5, your if condition will be true and the block of code that follows the condition will be executed.
    This number is Positive
  • Case 2: if you entered zero or a negative digit like -5, your if condition will be false and the block of code that follows the condition will not be executed which means that nothing will appear on your result screen.

else

The else statement in C++ is used to provide an alternate block of code to be executed if the condition of an if statement is false.

The general syntax of an else statement is as follows:

if (condition) {
  // code to execute if the condition is true
} else {
  // code to execute if the condition is false
}

For example, the following code uses an else statement to print a different message depending on whether the number variable is positive or negative:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    if (x > 0)
        cout << "This number is positive" << endl;
    else
        cout << "This number is negative" << endl;


    return 0;
}

Output should be one of the previous statements depending on the entered number. if the number is positive like 5, the output will be “This number is positive” and vice versa.

The else statement is a powerful tool for controlling the flow of your program. By using else statements, you can write more complex and efficient code.

Here are some general rules for using the if else statement:

  • The else statement must be used in conjunction with an if statement.
  • The else statement can be used to provide an alternate block of code to be executed if the condition of the if statement is false.
  • You can use nested if else statements to create more complex conditional statements:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int x = 0;
        cin >> x;
        if (x % 2 == 0)
            if (x > 50)
                cout << "it's Ok" << endl;
            else
                cout << "it's not Ok" << endl;
        else
            cout << "Odd" << endl;
    
    
        return 0;
    }
    

By understanding how to use the if else statement, you can write more efficient and reliable C++ code.

else if

Logical Operators

Logical operators in C++ are used to combine or modify Boolean expressions. They allow you to create more complex conditional statements.

The three logical operators in C++ are:

  • And (&&): Returns true if both of its operands are true. Otherwise, it returns false.
  • Or (||): Returns true if either of its operands is true. Otherwise, it returns false.
  • Not (!): Negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.

Logical operators can be used to create more complex conditional statements. For example, the following code uses the && operator to check if a digit is in a specific range of numbers or not:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cout << "Enter a number";
    cin >> x;
    if (x >= 1 && x <= 100)
        cout << "Ok" << endl;
    else
        cout << "Out of range" << endl;

    return 0;
}

Another Example:

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    cout << "Enter your age";
    cin >> a;
    char g = '\0';
    cout << "Enter your gender";
    cin >> g;
    
    if (a < 18 && g == 'm')
        cout << "male, " << "young boy" << endl;
    else if (a >= 18 && g == 'm')
        cout << "male," << "grown up man" << endl;
    else if (a < 18 && g == 'f')
        cout << "female," << "young girl" << endl;
    else
        cout << "female," << "grown up girl" << endl;
    
    return 0;
}

Note : \0 in C++ is a null character. It is a character with all bits set to zero. It is used to mark the end of a string in C++.

The following code uses the || operator to check if a number is greater than 10 or less than 5:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (number > 10 || number < 5) 
        cout << "The number is greater than 10 or less than 5." << endl;
    
    return 0;
}

The following code uses the ! operator to negate the value of the Boolean expression number > 10:

#include <iostream>

using namespace std;

int main()
{
    int number = 3;

    if (! (number > 10)) 
        cout << "The number is not greater than 10." << endl;
    
    return 0;
}

Logical operators can be used to create very complex conditional statements. However, it is important to use them carefully to avoid making your code difficult to read and maintain.

Here are some general rules for using logical operators:

  • Logical operators can be used to combine Boolean expressions to create more complex conditional statements.
  • The && operator returns true if both of its operands are true. Otherwise, it returns false.
  • The || operator returns true if either of its operands is true. Otherwise, it returns false.
  • The ! operator negates the value of its operand. If the operand is true, it returns false. Otherwise, it returns true.
  • Logical operators can be used in nested expressions.

By understanding how to use logical operators, you can write more efficient and reliable C++ code.

Selection Statement – Switch Statement

Selection statements in C++ are used to control the flow of a program. They allow you to execute different blocks of code based on different conditions.

The two main selection statements in C++ are:

  • if statement: The if statement allows you to execute a block of code if a condition is true.
  • switch statement: The switch statement allows you to select one of multiple blocks of code based on the value of an expression.

We explained “if statement” in “Selection Statement – if Statement” section, and now we are going to explain more about “switch statement”.

The switch statement in C++ is a control statement that allows you to execute different blocks of code based on the value of an expression. The general syntax of a switch statement is as follows:

switch (expression) {
  case value1:
    // code to execute if expression equals value1
  case value2:
    // code to execute if expression equals value2
  ...
  default:
    // code to execute if expression does not equal any of the values in the case statements
}

The expression can be any integer expression. The switch statement evaluates the expression and compares it to the values of the case statements. If the expression equals one of the values in the case statements, the code block inside that case statement is executed. If the expression does not equal any of the values in the case statements, the code block inside the default statement is executed.

Here is an example of a switch statement:

#include <iostream>

using namespace std;

int main()
{
    int x = 0;
    cin >> x;
    
    switch (x)
    {
        case 1: cout << "case #1" << endl;
            break;
        case 2: cout << "case #2" << endl;
            break;
        case 3: cout << "case #3" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

You can also use characters instead of numbers in switch statement. For Example:

#include <iostream>

using namespace std;

int main()
{
    char c = 'a';
    
    switch (c)
    {
        case 'a': cout << "case #a" << endl;
            break;
        case 'b': cout << "case #b" << endl;
            break;
        default:
            cout << "Out of range" << endl;
            break;
    }
    
    return 0;
}

Output will be:

case #a

Remember!
Using a capital letter like ‘A’ in the previous example is not like using a small letter like ‘a’. They are not the same!

Benefits of using switch statements

Switch statements can be more efficient than using a series of if statements, especially when there are many different cases. Switch statements can also make your code more readable and maintainable.

Conclusion

Switch statements are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Repetition Statement

A repetition statement in C++ is a control statement that allows you to execute a block of code repeatedly until a certain condition is met. There are three types of repetition statements in C++:

  • while loop: The while loop executes a block of code repeatedly while a condition is true.
  • do-while loop: The do-while loop executes a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again.
  • for loop: The for loop executes a block of code a fixed number of times.

Repetition statements are a powerful tool for controlling the flow of your C++ program. They can be used to solve a variety of problems, such as:

  • Iterating over a collection of data
  • Performing a task a certain number of times
  • Waiting for a certain event to occur

While Loop

The while loop in C++ is a control statement that allows you to execute a block of code repeatedly while a condition is true. The general syntax of a while loop is as follows:

while (condition) {
  // code to execute while the condition is true
}

The condition can be any Boolean expression. The while loop evaluates the condition and if it is true, the code block inside the while loop is executed. The code block inside the while loop is executed repeatedly until the condition evaluates to false.

Here is an example of a while loop:

#include <iostream>

using namespace std;

int main()
{
    while (true)
    {
        cout << " a word" <<endl;
    }
    
    return 0;
}

The previous code is a simple infinite loop in C++. It will print the phrase “a word” to the console forever, or until the program is terminated.

The while (true) statement creates an infinite loop. This means that the code block inside the loop will be executed forever, or until the program is terminated.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler evaluates the condition of the while statement. Since the condition is always true, the code block inside the loop is executed.
  2. The compiler prints the phrase “a word” to the console.
  3. The compiler goes back to step 1 and repeats the process.

This process continues forever, or until the program is terminated.

To terminate the program, you can press Ctrl+C on your keyboard.

Here are some things to keep in mind about infinite loops:

  • Infinite loops can be useful for certain tasks, such as polling for input or waiting for a certain event to occur.
  • However, it is important to use infinite loops carefully, as they can also cause your program to crash if you are not careful.
  • For example, if you accidentally create an infinite loop that prints output to the console, your console window will quickly fill up with output and your program will become unresponsive.

To overcome these problems we should make 3 steps:

  1. declare a variable and initializes it to any value we want.
  2. add a condition to while statement.
  3. set a counter for our variable.

These steps are shown in the following example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0;
    while (c < 5)
    {
        cout << " a word" <<endl;
        c++;
    }
    
    return 0;
}

int c = 0;, declares an integer variable named c and initializes it to the value 0.

The while (c < 5) statement creates a loop that will iterate as long as the value of the c variable is less than 5.

The cout << " a word" << endl; statement prints the phrase “a word” to the console. The endl; object at the end of the line inserts a newline character, which causes the next line of output to be printed on a new line.

The c++; statement increments the value of the c variable by 1.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the c variable and initializes it to the value 0.
  2. The compiler evaluates the condition of the while statement. Since the condition is true, the code block inside the loop is executed.
  3. The compiler prints the phrase “a word” to the console.
  4. The compiler increments the value of the c variable by 1.
  5. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 5. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

Here is the output of this program:

a word
a word
a word
a word
a word

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    while (c < 4)
    {
        cout << "Enter a number: ";
        cin >> num;
        sum = sum + num;
        c++;
    }
    cout << " sum = " << sum << endl;
    return 0;
}

This code is a simple C++ program that prompts the user to enter four numbers and then prints the sum of those numbers to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The while (c < 4) statement creates a loop that will iterate as long as the value of the c variable is less than 4.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum = sum + num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The compiler goes back to step 2 and repeats the process.

This process continues until the value of the c variable is equal to 4. At that point, the condition of the while statement will evaluate to false and the loop will terminate.

After the loop has terminated, the program prints the message ” sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
 sum = 100

While loops are a powerful tool for controlling the flow of your C++ program. By understanding how to use them, you can write more efficient and reliable code.

Here are some tips for using while loops:

  • Make sure that the condition of the while loop will eventually evaluate to false. Otherwise, the while loop will run forever.
  • Use a break statement to exit the while loop early.
  • Use a continue statement to skip the rest of the current iteration of the while loop.

Do - while loop

The do-while loop in C++ is a control statement that allows you to execute a block of code at least once, and then it evaluates a condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

The general syntax of a do-while loop is as follows:

do {
  // code to execute
} while (condition);

The condition can be any Boolean expression. The do-while loop executes the code block at least once, and then it evaluates the condition. If the condition is true, the code block is executed again. The code block is executed repeatedly until the condition evaluates to false.

Here is an example of a do-while loop:

#include <iostream>

using namespace std;

int main()
{
    int c = 0, num = 0, sum = 0;
    do
    {
        cout << "Enter a number: ";
        cin >> num;
        sum += num;
        c++;
    }
    while (c <= 4);
    cout << "sum = " << sum << endl;
    return 0;
}

This code prompts the user to enter four numbers and then prints the sum of those numbers to the console. The program uses a do-while loop to ensure that the user enters at least one number, even if they enter an invalid number the first time.

Here is a step-by-step explanation of what happens when you run this code:

  1. The compiler declares the cnum, and sum variables and initializes them to the values 0, 0, and 0, respectively.
  2. The do statement begins the do-while loop.
  3. The cout << "Enter a number: "; statement prints the message “Enter a number: ” to the console.
  4. The cin >> num; statement reads a number from the user and stores it in the num variable.
  5. The sum += num; statement increments the value of the sum variable by the value of the num variable.
  6. The c++; statement increments the value of the c variable by 1.
  7. The while (c <= 4); statement evaluates the condition of the do-while loop. If the c variable is less than or equal to 4, the loop will continue to iterate. Otherwise, the loop will terminate.
  8. If the condition of the loop is true, the code block inside the loop is executed.
  9. Steps 3-7 are repeated until the condition of the loop is false.
  10. After the loop has terminated, the program prints the message “sum = ” to the console, followed by the value of the sum variable.

Here is an example of the output of this program:

Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
sum = 100

Do-while loops can be used to solve a variety of problems, such as:

  • Validating user input
  • Checking for a certain condition to be met
  • Performing a task a certain number of times

The differences between while loop and do – while loop:

Feature While loop Do-while loop
Condition is checked Before the code block is executed. After the code block is executed.
Guarantee of execution The code block is not guaranteed to be executed at least once. The code block is guaranteed to be executed at least once.

Table explanation

  • While loop: The while loop checks the condition before the code block is executed. If the condition is true, the code block is executed. The code block is executed repeatedly until the condition evaluates to false.
  • Do-while loop: The do-while loop checks the condition after the code block is executed. The code block is executed at least once, regardless of the value of the condition. The code block is executed repeatedly until the condition evaluates to false.

For loop

The for loop in C++ is a control statement that allows you to execute a block of code repeatedly a certain number of times. The general syntax of a for loop is as follows:

for (initialization; condition; increment) {
  // code to execute
}

The initialization statement is executed once, before the for loop starts. The condition statement is evaluated before each iteration of the loop. If the condition is true, the code block inside the loop is executed. The increment statement is executed after each iteration of the loop.

Here is an example of a for loop:

#include <iostream>

using namespace std;

int main()
{
    
    for (int c = 0; c < 10; c++)
    {
        cout << c << endl;
    }
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the c variable to 0.
  2. The condition statement checks if the c variable is less than 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the c variable to the console.
  4. The increment statement increments the c variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

0
1
2
3
4
5
6
7
8
9

Here is another example that prompts the user to enter 10 marks and then prints the average of those marks to the console:

#include <iostream>

using namespace std;

int main()
{
    int m = 0, sum = 0;
    for (int i = 1; i <= 10; i++)
    {
        cout << "Enter your marks:";
        cin >> m;
        sum = sum + m;
    }
    cout << "the avg = " << ((double)sum / 10) << endl;
    
    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 1.
  2. The condition statement checks if the i variable is less than or equal to 10. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prompts the user to enter their marks and stores the value in the m variable. The code block also adds the value of the m variable to the sum variable.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

After the for loop has terminated, the program prints the average of the marks to the console. The average is calculated by dividing the sum of the marks by the number of marks.

You used the (double) cast in the expression ((double)sum / 10) to ensure that the result of the division operation is a floating-point number. This is important because the sum variable is an integer variable, and the division of two integers results in an integer. If you did not use the (double) cast, the program would print the integer result of the division operation to the console, which may not be accurate.

Here is an example of the output of this program:

Enter your marks: 10
Enter your marks: 20
Enter your marks: 30
Enter your marks: 40
Enter your marks: 50
Enter your marks: 60
Enter your marks: 70
Enter your marks: 80
Enter your marks: 90
Enter your marks: 100
the avg = 55.000000

This code prints the numbers from 10 to 50 to the console, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i <= 50; i++)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is less than or equal to 50. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The increment statement increments the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Why is size_t used as the loop counter?

The size_t type is used as the loop counter because it is the type that is returned by the sizeof operator. This ensures that the loop counter can be used to iterate over any type of data, including arrays and objects.

This code prints the numbers from 10 to 1 to the console, in reverse order, separated by spaces:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 10; i >= 1; i--)
    {
        cout << i << " ";
    }

    return 0;
}

The for loop works as follows:

  1. The initialization statement initializes the i variable to 10.
  2. The condition statement checks if the i variable is greater than or equal to 1. If it is, the code block inside the loop is executed.
  3. The code block inside the loop prints the value of the i variable to the console, followed by a space.
  4. The decrement statement decrements the i variable by 1.
  5. Steps 2-4 are repeated until the condition statement evaluates to false.

When the condition statement evaluates to false, the for loop terminates.

Here is the output of this program:

10 9 8 7 6 5 4 3 2 1

Examples of loop break vs continue

break and continue are two flow control statements in C++ that can be used to alter the normal flow of a loop.

break terminates the loop immediately and unconditionally.

continue skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is an example of how to use continue in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 5)
            continue;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 9, inclusive, except for the number 5. The if statement inside the loop checks if i is equal to 5. If it is, the continue statement skips the rest of the current iteration of the loop and causes the loop to continue with the next iteration.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 5.
  4. If i is equal to 5, the program skips the rest of the current iteration of the loop using the continue statement.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times.

Here is the output of this code:

i = 0
i = 1
i = 2
i = 3
i = 4
i = 6
i = 7
i = 8
i = 9

Here is an example of how to use break in C++:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        if (i == 4)
            break;
        cout << "i = " << i << endl;
    }
    
    return 0;
}

This code is a for loop that prints the values of the variable i to the console, from 0 to 3, inclusive. The if statement inside the loop checks if i is equal to 4. If it is, the break statement terminates the loop immediately and unconditionally.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares a variable i and initializes it to 0.
  2. The program starts a for loop that iterates 10 times.
  3. Inside the for loop, the program checks if i is equal to 4.
  4. If i is equal to 4, the break statement terminates the loop immediately and unconditionally.
  5. Otherwise, the program prints the value of i to the console.
  6. The program then increments i by 1.
  7. The for loop repeats steps 3-6 until it has iterated 10 times or until the loop is terminated by the break statement.

In this case, the loop will be terminated by the break statement when i is equal to 4. Therefore, the output of the code will be:

i = 0
i = 1
i = 2
i = 3

Which one to use?

Which one to use depends on what you want to achieve. If you want to terminate the loop immediately, use break. If you want to skip the rest of the current iteration of the loop and continue with the next iteration, use continue.

Here are some general tips for using break and continue:

  • Use break sparingly. Terminating a loop early can make your code more difficult to read and understand.
  • Use continue to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using continue.
  • Use break and continue to make your code more efficient. For example, you can use break to terminate a loop early if you have already found what you are looking for.

Nested Loop

A nested loop is a loop that is contained within another loop. This means that the inner loop will iterate for each iteration of the outer loop.

Here is an example of a nested loop in C++:

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= 6; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

This code is a nested for loop that prints a rectangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates 6 times. This means that the code inside the inner loop will be executed 30 times.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 6. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 6.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

******
******
******
******
******

Nested loops can be used to solve a variety of problems. For example, you could use nested loops to iterate over all the elements of a two-dimensional array, or to generate all the possible combinations of two sets of values.

Here are some tips for using nested loops:

  • Use nested loops sparingly. Nested loops can make your code more difficult to read and understand.
  • Use nested loops to avoid writing duplicate code. If you find yourself writing the same code inside a loop multiple times, consider using nested loops.
  • Use nested loops to make your code more efficient. For example, you can use nested loops to avoid searching for an element in an array multiple times.

Draw shapes (Triangle)

You can use the logic of nested loops to create different shapes, for example a triangle.

This code is a nested for loop that prints a triangle of asterisks to the console. The outer loop iterates 5 times, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 5.

Here is the output of the code:

*
**
***
****
*****

What if we want to draw this triangle upside down?

We change the condition in our outer for loop.

This code is a nested for loop that prints an inverted triangle of asterisks to the console. The outer loop iterates from 5 to 1, inclusive, and the inner loop iterates for each iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 1; j <= i; j++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 5 and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is greater than or equal to 1. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to i. If it is, the program prints an asterisk to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than i.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then decrements i by 1.
  9. The outer for loop repeats steps 3-8 until i is less than 1.

Here is the output of the code:

*****
****
***
**
*

Can we make it harder?

This code prints a right triangle of asterisks to the console. The outer loop iterates from 1 to 5, inclusive, and the inner loop iterates from 4 to i, inclusive, where i is the current iteration of the outer loop.

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 1; i <= 5; i++)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares three variables ij, and k, and initializes them to 1, 4, and 1, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is greater than or equal to i. If it is, the program prints a space to the console.
  5. The inner for loop then decrements j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is less than i.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments i by 1.
  10. The outer for loop repeats steps 3-9 until i is greater than 5.

Here is the output of the code:

    *
   **
  ***
 ****
*****

Let’s print it upside down!

#include <iostream>

using namespace std;

int main()
{
    for ( size_t i = 5; i >= 1; i--)
    {
        for ( size_t j = 4; j >= i; j--)
        {
            cout << " ";
        }
        for (size_t k = 1; k <= i; k++)
        {
            cout << "*";
        }
        cout << endl;
    }

    return 0;
}

Look what we have here as an output!

*****
 ****
  ***
   **
    *

Let’s draw a different triangle

#include <iostream>

using namespace std;

int main()
{
    int e = 1;
    for (int a = 1; a <= 5; a++)
    {
        for (int b = 4; b >= a; b--)
        {
            cout << " ";
        }
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e + 2;
    }

    return 0;
}

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares four variables ea, c, and b, and initializes them to 1, 1, 0 and 4, respectively.
  2. The program starts the outer for loop.
  3. The outer for loop checks if a is less than or equal to 5. If it is, the inner for loop is executed.
  4. The inner for loop checks if b is greater than or equal to a. If it is, the program prints a space to the console.
  5. The inner for loop then decrements b by 1.
  6. The inner for loop repeats steps 4 and 5 until b is less than a.
  7. After the inner for loop has terminated, the program prints an asterisk to the console for each iteration of the inner for loop.
  8. The program then prints a newline character to the console.
  9. The outer for loop then increments a by 1.
  10. The outer for loop repeats steps 3-9 until a is greater than 5.

Here is the output of the code:

    *
   ***
  *****
 *******
*********

Let’s make it upside down:

#include <iostream>

using namespace std;

int main()
{
    int e = 9;
    for (int r = 1; r <= 5; r++)
    {
        for (int c = 0; c < e; c++)
        {
            cout << "*";
        }
        cout << endl;
        e = e - 2;
        for (int s = 0; s < r; s++)
        {
            cout << " ";
        }
    }

    return 0;
}

Output:

*********
 *******
  *****
   ***
    *

You can also use nested loops to draw other shapes, such as squares, rectangles, and diamonds.

Draw shapes (square), Draw any Letter Ex:( X,Z,N,E,F)

Nested loops in C++ are a powerful tool for drawing different shapes to the console. By using nested loops, we can iterate over multiple dimensions and print different characters to create different patterns.

Example 1:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == 1 || i == 10)
                cout << "*";
            else if (j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

This code prints a hollow square of asterisks to the console. The outer for loop iterates from 1 to 10, inclusive, and the inner for loop iterates from 1 to 10, inclusive.

The if statement inside the inner for loop checks if i is equal to 1 or 10, or if j is equal to 1 or 10. If any of these conditions are met, the program prints an asterisk to the console. Otherwise, the program prints a space to the console.

Here is a step-by-step explanation of what happens when you run this code:

  1. The program declares two variables i and j, and initializes them to 1.
  2. The program starts the outer for loop.
  3. The outer for loop checks if i is less than or equal to 10. If it is, the inner for loop is executed.
  4. The inner for loop checks if j is less than or equal to 10. If it is, the program prints an asterisk to the console if i is equal to 1 or 10, or if j is equal to 1 or 10. Otherwise, the program prints a space to the console.
  5. The inner for loop then increments j by 1.
  6. The inner for loop repeats steps 4 and 5 until j is greater than 10.
  7. After the inner for loop has terminated, the program prints a newline character to the console.
  8. The outer for loop then increments i by 1.
  9. The outer for loop repeats steps 3-8 until i is greater than 10.

Here is the output of the code:

**********
*        *
*        *
*        *
*        *
*        *
*        *
*        *
*        *
**********

Example 2:

If we want to print a letter like X to the console, expecting an output like this:

*   *
 * * 
  *  
 * * 
*   *

We need to set our logic.
To understand how we can put the asterisks in the previous shape, let’s present them this way:

/*
 1 2 3 4 5
1* * * * *
2* * * * *
3* * * * *
4* * * * *
5* * * * *
*/

Now let’s think about it looking at this shape, when the column meets the row we get a star, so we need a loop that goes through all the meeting points between every row and column and we need an if condition to specify our exact locations to make two diagonal lines cross forming our X letter shape.

all of this is represented in the following code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (i == j || j == 6-i)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Example 3:

By understanding how we asterisks are lined here:

/*
 1 2 3 4 5 
1* * * * * 
2* * * * * 
3* * * * * 
4* * * * * 
5* * * * * 
*/

We can think of multiple ways to manipulate our code producing different letters and shapes..

Look at this code:

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 5; i++)
    {
        for (size_t j = 1; j <= 5; j++)
        {
            if (j == (6) - i || i == 1 || i == 5)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

Guess what this shape is?!

Output:

*****
   *
  *  
 *   
*****

Example 4:

Now let’s make our shape more complicated

**********
**      **
* *    * *
*  *  *  *
*   **   *
*   **   *
*  *  *  *
* *    * *
**      **
**********

Applying this code which is no different than previous examples

#include <iostream>

using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        for (size_t j = 1; j <= 10; j++)
        {
            if (i == j || j == 11 - i || i == 1 || i == 10 || j == 1 || j == 10)
                cout << "*";
            else
                cout << " ";
        }
        cout << endl;
    }

    return 0;
}

 

Function Part 1

A function in C++ is a block of code that performs a specific task. Functions can be used to encapsulate common operations, making your code more reusable and easier to understand. Functions can also be used to improve the performance of your code by avoiding duplicate code.

To create a function in C++, you use the following syntax:

return_type function_name(parameter_list) {
  // Function body
}

The return_type specifies the type of data that the function will return. The function_name is the name of the function. The parameter_list is a list of parameters that the function will accept. The function_body is the code that the function will execute.

Here is an example of a simple function in C++:

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}

This function takes two integer parameters, x and y, and returns the sum of those two parameters.

To call a function, you simply use its name followed by a pair of parentheses. For example, to call the sum() function, you would write:

int s = sum(10, 20);

This would assign the value 30 to the variable s.

The code could be written this way:

#include <iostream>

using namespace std;

int sum(int x, int y)
{
    int s = 0;
    s = x + y;
    return s;
}
int main()
{
    int s = 0;
    s = sum(10, 20);
    cout << "sum = " << s << endl;
    
    return 0;
}

The following example takes two float parameters and return the sum of them:

#include <iostream>

using namespace std;

float sum(float x, float y)
{
    float s = 0;
    s = x + y;
    return s;
}
int main()
{
    float s = 0;
    s = sum(20.5, 30.6);
    cout << "sum = " << s << endl;
    
    return 0;
}

Output:

sum = 51.1

The importance of using return:

We need to write a return in a function in C++ to specify the value that the function will return to the calling function. This is important because it allows us to use the function to perform calculations and then use the result of those calculations in our code.

Without the return statement, the function would not be able to return any value to the calling function. This would mean that we would not be able to use the function to perform calculations and then use the result of those calculations in our code.

By using the return statement, we can terminate the execution of the function early and avoid the error. This makes our code more robust and reliable.

Overall, the return statement is an important part of C++ programming. It allows us to return values from functions and to terminate the execution of functions early. This makes our code more reusable, efficient, and reliable.

But can we write a function without using return?

See this example:

#include <iostream>

using namespace std;

void print()
{
    cout << "myName" << endl;
}

int main()
{
    print();
    
    return 0;
}

This code defines a function called print() and a main function. The print() function simply prints the string “myName” to the console. The main function calls the print() function and then returns 0.

The print() function is declared with the void return type. This means that the function does not return any value. We use the void return type when we want a function to perform an action but not return any value.

When you run this code, the following output will be printed to the console:

myName

We use the void return type for the print() function because we only want it to print the string “myName” to the console. We do not need the function to return any value.

 

Functions can also be nested, meaning that one function can call another function. This can be useful for breaking down complex tasks into smaller, more manageable functions.

Functions are a powerful tool in C++ and can be used to improve the quality and performance of your code.

Here are some tips for using functions in C++:

  • Give your functions meaningful names. This will make your code more readable and easier to maintain.
  • Use functions to encapsulate common operations. This will make your code more reusable and easier to understand.
  • Use functions to improve the performance of your code by avoiding duplicate code.
  • Use functions to break down complex tasks into smaller, more manageable functions.

Function Part 2

Example 1:

#include <iostream>

using namespace std;

double avg(int m1, int m2, int m3) 
{
    return double(m1 + m2 + m3) / 3;
}

int main()
{
    int mm1, mm2, mm3;
    cout << "Enter your marks" << endl;
    cin >> mm1 >> mm2 >> mm3;
    cout << "avg = " << avg(mm1, mm2, mm3) << endl;
    
    return 0;
}

This code defines a function called avg(), which takes three integer parameters (m1, m2, and m3) and returns the average of those three parameters as a double value.

The function works by first converting the integer parameters to double values using the double() function. This is necessary because the average of three integers is a fractional number, and we want the function to return a double value.

Next, the function calculates the sum of the three parameters and divides that sum by 3. This gives us the average of the three parameters.

Finally, the function returns the average value.

The program works as follows:

  1. The program declares three integer variables mm1mm2, and mm3 to store the marks entered by the user.
  2. The program prompts the user to enter their marks and reads the marks into the three variables.
  3. The program calls the avg() function to calculate the average of the three marks.
  4. The program prints the average to the console.

Example 2:

#include <iostream>

using namespace std;

int max(int n1, int n2, int n3) 
{
    int mx = n1;
    if (mx < n2)
        mx = n2;
    if (mx < n3)
        mx = n3;
    return mx;
}

int min(int n1, int n2, int n3) 
{
    int mn = n1;
    if (mn > n2)
        mn = n2;
    if (mn > n3)
        mn = n3;
    return mn;
}

int main()
{
    cout << "max = " << max(100, 200, 300) << endl;
    cout << "min = " << min(100, 200, 300) << endl;
    
    return 0;
}

This code defines two functions called max() and min()which both take three integer parameters (n1, n2, and n3) and returns the largest and the smallest of those three parameters.

The first function works by first initializing a variable called mx to the value of the first parameter, n1. Then, the function checks if mx is less than the second parameter, n2. If it is, the function assigns the value of n2 to mx. Next, the function checks if mx is less than the third parameter, n3. If it is, the function assigns the value of n3 to mx. Finally, the function returns the value of mx, which is the largest of the three parameters.

The second function works by first initializing a variable called mn to the value of the first parameter, n1. Then, the function checks if mn is greater than the second parameter, n2. If it is, the function assigns the value of n2 to mn. Next, the function checks if mn is greater than the third parameter, n3. If it is, the function assigns the value of n3 to mn. Finally, the function returns the value of mn, which is the smallest of the three parameters.

Here is the output of the program:

min = 100
max = 300

There are two ways to define a function in a C++ program:

  1. Function declaration: This is a prototype of the function that tells the compiler about the function’s name, return type, and parameters. The function declaration must be placed before the first call to the function.
  2. Function definition: This is the actual code that implements the function. The function definition can be placed anywhere in the program, but it is generally placed at the end of the program.

For example, here is a function declaration and definition:

// Function declaration
int add(int a, int b);

// Function definition
int add(int a, int b) {
  return a + b;
}

The function declaration tells the compiler that there is a function called add() that takes two integer parameters and returns an integer value. The function definition provides the actual code that implements the function.

You can also arrange function declarations and definitions in different ways in your code. For example, you can:

  • Declare all of your functions at the beginning of your program and then define them at the end of your program.
  • Declare and define your functions in the order that they are called in your program.
  • Declare your functions in a header file and define them in a source file.

The best arrangement for your code will depend on the specific needs of your program.

Here is an example of how to use function declarations and definitions in a C++ program:

// Function declaration
int add(int a, int b);

int main() {
  // Function call
  int sum = add(1, 2);

  // Print the sum
  cout << "The sum is: " << sum << endl;

  return 0;
}

// Function definition
int add(int a, int b) {
  return a + b;
}

Of course you should pay a massive attention to the sequential arrangement of your program.

The sequential arrangement of functions in a C++ program is important for two main reasons:

  • Readability: A well-organized program is easier to read and understand. By arranging functions in a logical order, you can make it easier for other programmers to follow the flow of your code.
  • Maintainability: A well-maintained program is easier to update and fix bugs in. By arranging functions in a logical order, you can make it easier to find and fix problems in your code.

Note !

The main function is the entry point for all C++ programs. It is the first function that is called when the program is executed. The main function is responsible for initializing the program, calling other functions, and returning a value to the operating system.

The main function is important for several reasons:

  • It is the starting point for the program execution.
  • It is responsible for initializing the program.
  • It controls the flow of the program by calling other functions.
  • It returns a value to the operating system when the program terminates.

Without the main function, the program would not be able to start executing.

Here is an example of a simple main function in C++:

int main() {
  // Initialize the program
  // ...

  // Call other functions
  // ...

  // Return a value to the operating system
  return 0;
}

This main function initializes the program, calls other functions, and returns a value of 0 to the operating system.

You can use the main function to control the flow of your program by calling other functions. For example, you could write a function to calculate the sum of two numbers and then call that function from the main function.

You can also use the main function to return a value to the operating system. This value is used to indicate whether the program terminated successfully or not.

The main function is a very important part of any C++ program. It is the starting point for the program execution, and it controls the flow of the program.

Example 3:

#include <iostream>

using namespace std;

int avg(int x, int y, int z)
{
    return (x + y + z) / 3;
}

void print()
{
    cout << "Hello" << endl;
}

void xy()
{
    cout << 5 * 10 << endl;
}

int main()
{
    cout << "Nothing" << endl;
    return 0;
}

int f2()
{
    return 5;
}

This code defines four functions: avg(), print(), xy(), and f2(). The avg() function takes three integer parameters and returns the average of those three parameters. The print() function prints the string “Hello” to the console. The xy() function prints the product of 5 and 10 to the console. The f2() function returns the integer 5.

The main function in the code simply prints the string “Nothing” to the console and then returns 0.

When you run this code, the following output will be printed to the console:

Nothing

This is because the only function that is called from the main function is the cout << "Nothing" << endl; statement.

You can use the other functions in the code by calling them from the main function or from other functions.

Function part 3 (built in functions)

Built-in functions in C++ are functions that are provided by the compiler and are available to use in any C++ program. These functions are typically used for common tasks such as input/output, mathematical operations, and string manipulation.

Here are some of the most common built-in functions in C++:

  • Mathematical functions:
    • abs(): Returns the absolute value of a number.
    • sqrt(): Calculates the square root of a number.
    • pow(): Raises a number to a power.
    • sin(): Calculates the sine of an angle in radians.
    • cos(): Calculates the cosine of an angle in radians.
    • tan(): Calculates the tangent of an angle in radians.
    • floor(): Returns the greatest integer less than or equal to a number.
    • ceil(): Returns the smallest integer greater than or equal to a number.
  • String manipulation functions:
    • strlen(): Returns the length of a string.
    • strcpy(): Copies one string to another string.
    • strcat(): Concatenates two strings.
    • strcmp(): Compares two strings and returns an integer value indicating whether they are equal, less than, or greater than each other.
  • Input/output functions:
    • cin: Reads data from the standard input stream.
    • cout: Writes data to the standard output stream.
    • cerr: Writes data to the standard error stream.
    • fopen(): Opens a file for reading or writing.
    • fclose(): Closes a file.

Example 1:

cout << sqrt(18) << endl;

Output:

4.24264

Example 2:

cout << abs(-18) << endl;

Output:

18

Example 3:

cout << mod(10.5,2) << endl;

Output:

0.5

Example 4:

cout << floor(10.2) << endl;

Output:

10

Example 5:

cout << floor(-10.2) << endl;

Output:

-11

Example 6:

cout << ceil(10.2) << endl;

Output:

11

Example 7:

#include <iostream>

using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

To use a built-in function, you simply need to include the appropriate header file. So you might have a problem executing this program. you would need to include the <cmath> header file.

The <cmath> header file contains declarations for a number of mathematical functions, such as sqrt(), pow(), sin(), cos(), and tan(). These functions are useful for performing common mathematical operations, such as calculating the square root of a number, raising a number to a power

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    cout << sqrt(abs(pow(-3,2))) << endl;

    return 0;
}

Output:

3

Example 8:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(10,5) << endl;

    return 0;
}

You would need to include the <algorithm> header file to use any of the algorithms provided by the C++ standard library. These algorithms include sorting, searching, merging, and many more.

Output:

10

Example 9:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    cout << max(15,max(10,5)) << endl;

    return 0;
}

Output:

15

Example 10:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int main()
{
    
    int x = 0, y = 10;
    swap(x,y);
    cout << "x= " << x << "y= " << y << endl;

    return 0;
}

Output:

x= 10y= 0

Built-in functions can be a very useful tool for C++ programmers. By using built-in functions, you can avoid having to write your own code for common tasks.

 

 

Function part 4 (Random functions)

Random functions in C++ are used to generate random numbers. There are two built-in random functions in C++: rand() and srand().

The rand() function generates a random integer between 0 and RAND_MAX, where RAND_MAX is a macro that is defined in the cstdlib header file. The srand() function is used to seed the random number generator. If you don’t call srand(), the random number generator will be seeded with a default value.

Example 1:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    
    cout << rand() << endl;
    
    return 0;
}

This code prints a random integer to the console.

Example 2:

#include <iostream>
#include <cstdlib>

using namespace std;
int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand() << endl;
    }
    
    return 0;
}

This code is a for loop that prints 10 random integers to the console.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 0; i < 10; i++)
    {
        cout << rand()%10 << endl;
    }
    
    return 0;
}

This code generates a random number between 0 and 9 and prints it to the console. The modulus operator (%) returns the remainder of a division operation. So, the expression rand()%10 will return the remainder of the operation rand() / 10. This will give us a number between 0 and 9.

Example 4:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

This code generates a random number between 20 and 30 and prints it to the console.

Example 5:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    srand(time(0));
    for (size_t i = 1; i <= 10; i++)
    {
        cout << rand()%(30 - 20 + 1) + 20 << endl;
    }
    
    return 0;
}

The srand(time(0)); function seeds the random number generator with the current time. This ensures that the random numbers are different each time the program is run.

The srand() function takes an integer seed as its argument and initializes the random number generator with that seed. The time(0) function returns the current time as a time_t value, which is an integer.

By seeding the random number generator with the current time, we are using a value that is constantly changing, which ensures that the random numbers are different each time the program is run.

It is important to seed the random number generator before using the rand() function. If you do not seed the random number generator, it will be seeded with a default value, which will result in the same sequence of random numbers being generated each time the program is run.

Example 6:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    int x, y;
    x = time(0);
    for (size_t i = 0; i < 10000; i++)
    {
        cout << time(NULL) << endl;
        y = time (0);
    }
    cout << "The token time:" << y - x << endl;
    return 0;
}

This code prints the current time 10000 times to the console and then prints the total time it took to do so.

The program works as follows:

  1. The int x, y; declaration creates two integer variables, x and y.
  2. The x = time(0); statement assigns the current time to the variable x.
  3. The for (size_t i = 0; i < 10000; i++) loop iterates 10000 times.
  4. On each iteration of the for loop, the following code is executed:
    • The current time is printed to the console using the cout << time(NULL) << endl; statement.
  5. The y = time(0); statement assigns the current time to the variable y.
  6. The cout << "The token time:" << y - x << endl; statement prints the total time it took to print the current time 10000 times to the console.

The time(NULL) function is a synonym for the time(0) function.

You can use this code to measure the performance of your code or to calculate the elapsed time between two events.

Function part 5 (Call By Reference vs Call By Value)

Call by value and call by reference are two different ways to pass arguments to functions in C++.

Call by value is the default passing mechanism in C++. When a function is called by value, a copy of the actual argument is passed to the function. The function then operates on this copy, and any changes made to the copy inside the function will not be reflected in the actual argument outside the function.

Call by reference allows you to pass the reference of the actual argument to the function. This means that the function operates directly on the actual argument outside the function. Any changes made to the argument inside the function will be reflected in the actual argument outside the function.

To pass an argument by reference, you need to use the & operator before the argument name

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void swap(int x, int y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 10 y= 20

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void swap(int&x, int&y)
{
    int z = x;
        x = y;
        y = z;
}

int main()
{
    int x = 10, y = 20;
    swap(x, y);
    cout << "x= " << x << " y= " << y << endl;
    
    return 0;
}

//x= 20 y= 10

As you can see, the result of calling the swap() function is different depending on whether it is called by value or by reference.

Call by reference is often used to modify the values of the arguments outside the function. For example, the swap() function could be used to swap the values of two variables.

Call by reference can also be used to pass large objects to functions without having to copy them. This can improve the performance of your program.

However, it is important to use call by reference carefully, as it can lead to unexpected results if not used correctly. For example, if you pass a reference to a local variable to a function, and the function returns, the local variable will go out of scope, but the reference to it will still be valid. This can lead to a program crash if you try to access the local variable through the reference.

In general, it is best to use call by value unless you have a specific reason to use call by reference.

For example, the following code shows how to call a function by value:

#include <iostream>
using namespace std;

void fun(int x, int y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 50 R= 10

The following code shows how to call the same function by reference:

#include <iostream>
using namespace std;

void fun(int&x, int&y)
{
    x += 1;
    y += 2;
}
int main()
{
    int k = 50, r = 10;
    fun(k, r);
    cout << "K= " << k << " R= " << r << endl;
    
    return 0;
}

//K= 51 R= 12

As you can see, the result of calling the fun() function is different depending on whether it is called by value or by reference.

Function part 6 (Recursion 1)

Recursion is a programming technique where a function calls itself directly or indirectly. This can be used to solve problems that can be broken down into smaller, simpler problems of the same type.

Recursion can be a bit difficult to understand at first, but it is a powerful tool that can be used to solve a wide variety of problems.

Here is a simple example of a recursive function in C++:

#include <iostream>
using namespace std;
void f(int n)
{
    if (n < 1)
        return;
    else
        cout << "round:" << n << endl;
    f(n - 1);
}

int main()
{
    f(5);
    return 0;
}

The function f(int n) is a recursive function that prints the string “round:” followed by the integer n to the console n times.

The function works by recursively calling itself to print the string “round:” followed by the integer n - 1 to the console. This process continues until n is equal to 1, at which point the function returns.

Output:

round: 5
round: 4
round: 3
round: 2
round: 1

Recursive functions can be a bit difficult to understand at first, but they are a powerful tool that can be used to solve a wide variety of problems.

You should pay attention to these 3 contents of a recursive function (base case, logic and subproblem), which are marked in the following function:

void f(int n)
{
    if (n < 1)
        return; //base case
    else
        cout << "round:" << n << endl; //logic
    f(n - 1); //subproblem
}

The three contents of a recursive function are:

  • Base case: The base case is a special case that is handled directly in the function without making any recursive calls. The base case is usually a simple case that can be solved directly.
  • Logic: The logic of a recursive function is the code that is executed to break down the problem into smaller, simpler problems of the same type. The logic usually involves making recursive calls to the function with smaller input values.
  • Subproblem: A subproblem is a smaller, simpler problem of the same type as the original problem. Recursive functions work by breaking down the original problem into subproblems and then solving the subproblems using the same recursive function.

Here is an example of a recursive function in C++ that calculates the factorial of a number:

#include <iostream>
using namespace std;
int fact(int n)
{
    if (n == 0 || n == 1)
        return 1;
    else
        return n*fact(n - 1);
}

int main()
{
    cout << fact(5) << endl;
    return 0;
}

The function fact(int n) is a recursive function that calculates the factorial of a number. The factorial of a number is the product of all the positive integers less than or equal to that number. For example, the factorial of 5 is 120, because 120 is the product of 1, 2, 3, 4, and 5. So, the  output of our program will be 120.

The function fact(int n) works by recursively calling itself to calculate the factorial of the number one less than the input number. For example, to calculate the factorial of 5, the function would first call itself to calculate the factorial of 4. This would then call itself to calculate the factorial of 3, and so on. Eventually, the function would reach the base case, where the input number is 0 or 1. The base case is a special case that is handled directly in the function without making any recursive calls. The factorial of 0 is 1 and the factorial of 1 is also 1, so the function simply returns 1 in these cases.

Fibonacci Series

The Fibonacci sequence is a series of numbers where each number is the sum of the two previous numbers. The first two numbers in the sequence are 0 and 1, and each subsequent number is the sum of the previous two numbers.

Here is the Fibonacci sequence up to the first 10 numbers:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The Fibonacci sequence can be generated using the following recurrence relation:

F(n) = F(n - 1) + F(n - 2)

where F(n) is the nth number in the Fibonacci sequence.

The Fibonacci sequence has a number of interesting properties. For example, the ratio of successive Fibonacci numbers approaches the golden ratio as the numbers get larger. The golden ratio is an irrational number that is approximately equal to 1.618.

The Fibonacci sequence appears in many different areas of mathematics and nature. For example, it can be used to model the growth of a population of rabbits, the spiral pattern of a seashell, and the branching pattern of a tree.

Here are some examples of how the Fibonacci sequence is used in the real world:

  • Finance: The Fibonacci sequence can be used to identify potential support and resistance levels for stock prices.
  • Music: The Fibonacci sequence can be used to create musical compositions with a pleasing rhythm and structure.
  • Art: The Fibonacci sequence can be used to create works of art with a balanced and harmonious composition.
  • Architecture: The Fibonacci sequence can be used to design buildings and other structures that are aesthetically pleasing and structurally sound.

The Fibonacci sequence is a fascinating and versatile mathematical sequence that has many applications in the real world.

Example:

#include <iostream>
using namespace std;
int fib(int n)
{
    if (n == 0 || n == 1)
        return n;
    else
        return fib(n - 1) + fib(n - 2);
}

int main()
{
    cout << fib(3) << endl;
    return 0;
}

The function fib(int n) works by recursively calling itself to calculate the Fibonacci numbers of the previous two numbers. If the input number n is 0 or 1, the function simply returns the number, because the first two Fibonacci numbers are 0 and 1. Otherwise, the function returns the sum of the Fibonacci numbers of the previous two numbers.

Output:

2

 

Function part 7 (Recursion 2)

Example 1:

#include <iostream>
using namespace std;
int sum(int n)
{
    if (n == 1)
        return 1;
    else
        return n + sum(n - 1);
}

int main()
{
    cout << sum(5) << endl;
    return 0;
}

This function calculates the sum of the first n natural numbers. The first n natural numbers are the numbers from 1 to n.

The function works by recursively calling itself to calculate the sum of the first n - 1 natural numbers. If the input number n is 1, the function simply returns the number 1, because the sum of the first natural number is 1. Otherwise, the function returns the sum of the input number n and the sum of the first n - 1 natural numbers.

Output:

15

Example 2:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    if (x == y)
        return x;
    else
        return y + sum(x, y - 1);
}

int main()
{
    cout << sum(4, 6) << endl;
    return 0;
}

This is a recursive function sum. It takes two integer parameters, x and y, which represent the range of numbers to sum. Here’s how the function works:

  • The base case: If x is equal to y, it means we have reached the end of the range, so it returns x. This is the terminating condition for the recursion.
  • The recursive case: If x is not equal to y, it adds the current value of y to the result of calling the sum function again with the same x and y-1. This effectively breaks down the sum of the range into smaller subproblems by reducing the upper bound (y) by 1 in each recursive call.

In the main function, it calls the sum function with the arguments 4 and 6 and then outputs the result to the console using cout. In this case, it will calculate the sum of integers from 4 to 6 (inclusive) and print the result.

When you run this code, it will output the sum of integers from 4 to 6, which is 4 + 5 + 6 = 15. So, the output of this code will be:

15

Function part 8 (Overloading Function)

Function overloading is a feature of C++ that allows you to have two or more functions with the same name, as long as they have different parameters. This can be useful when you want to have a single function that can perform different tasks, depending on the type of data that is passed to it as an argument.

For example, this code is a set of three C++ functions that print different types of data to the console.

#include <iostream>
using namespace std;

void print(int a)
{
    cout << "Integer = " << a << endl;
}
void print(float a)
{
    cout << "Float = " << a << endl;
}
void print(char c)
{
    cout << "Character = " << c << endl;
}

int main()
{
    print(1);
    print('a');
    return 0;
}

The first function, print(int a), takes an integer as an argument and prints it to the console with the prefix “Integer = “.

The second function, print(float a), takes a floating-point number as an argument and prints it to the console with the prefix “Float = “.

The third function, print(char c), takes a character as an argument and prints it to the console with the prefix “Character = “.

Output:

Integer = 1
Character = a

 

Function part 9 (Default arguments)

Default arguments are a feature of C++ that allows you to specify a default value for a function parameter. This means that if a caller of the function does not provide a value for a particular parameter, the default value will be used instead.

Default arguments can be useful for simplifying the code that calls a function, and for making the function more flexible. For example, you could have a function that takes two parameters, but where the second parameter is optional. You could then specify a default value for the second parameter, so that callers of the function do not have to provide a value for it if they do not want to.

Here is an example of how to use default arguments in C++:

#include <iostream>
using namespace std;

int sum(int a = 5, int b = 5, int c = 5)
{
    return a + b + c;
}

int main()
{
    cout << sum(10, 55) << endl;
    return 0;
}

This code calculates the sum of three integers. The program uses default arguments to provide default values for the three integers. This means that if the caller of the sum() function does not provide values for all three integers, the default values will be used instead.

The main() function calls the sum() function with the arguments 10 and 55. The sum() function will then return the sum of the three integers, which is 70. The main() function will then print the result to the console.

Output:

70

Here are some tips for using default arguments:

  • Do not write your default argument in the middle of two arguments like this (int a, int b = 5, int c), it will produce an error to the compiler.
  • Be careful not to overwrite default parameters with values that are not valid for the function.
  • Use default parameters to provide default values for parameters that are not essential to the function’s functionality.

Function part 10 (Inline Function)

An inline function in C++ is a function whose code is substituted at the point of call. This means that the compiler copies the code of the inline function into the calling function, instead of generating a call instruction.

Inline functions are typically used for small functions that are frequently called. This can improve the performance of the program, as it eliminates the overhead of function calls.

To declare an inline function in C++, you use the inline keyword before the function declaration. For example:

#include <iostream>
using namespace std;

inline void p()
{
    cout << "hello" << endl;
}

int main()
{
    p();
    p();
    p();
    return 0;
}

inline void p(), defines an inline function called p(). The function takes no arguments and simply prints the word “hello” to the console, followed by a newline character.

The three lines, p();, p();, and p();, call the p() function three times.

When the program is executed, the following output will be printed to the console:

hello
hello
hello

It is important to note that the compiler is not obligated to inline a function, even if it is declared as inline. The compiler may choose not to inline a function if it is too large or if it is called indirectly.

Here are some of the benefits of using inline functions:

  • Improved performance: Inline functions can improve the performance of a program by eliminating the overhead of function calls.
  • Reduced code size: Inline functions can reduce the code size of a program by removing the need to generate separate code for each function call.
  • Increased readability: Inline functions can make code more readable by eliminating the need to jump back and forth between different functions.

However, there are also some potential drawbacks to using inline functions:

  • Increased compile time: Inlining functions can increase the compile time of a program, as the compiler needs to copy the code of the inline function into each calling function.
  • Increased code size: If an inline function is called frequently, it can increase the code size of the program.
  • Reduced maintainability: Inline functions can make code more difficult to maintain, as the code for the inline function is scattered throughout the program.

Overall, inline functions can be a useful tool for improving the performance and readability of code. However, it is important to use them carefully, as they can also increase the compile time and code size of a program.

Here are some tips for using inline functions effectively:

  • Only inline small functions that are frequently called.
  • Avoid inlining functions that are too large or that are called indirectly.
  • Use the inline keyword consistently, so that the compiler can make informed decisions about whether or not to inline a function.
  • Document your code clearly, so that other developers understand how and why inline functions are being used.

Static variable

A static variable in C++ is a variable that is allocated once and remains in memory throughout the execution of the program. Static variables can be declared at global scope, namespace scope, class scope, or function scope.

Static variables at global scope are initialized when the program starts and are destroyed when the program ends. Static variables at namespace scope are initialized when the namespace is loaded and are destroyed when the namespace is unloaded. Static variables in classes are initialized when the class is first used and are destroyed when the program ends. Static variables in functions are initialized when the function is first called and are destroyed when the function returns.

Static variables can be useful for a variety of purposes, such as:

  • Storing global state information: Static variables can be used to store global state information that needs to be accessed by multiple functions in a program.
  • Implementing singletons: Static variables can be used to implement singletons, which are classes that can only have one instance.
  • Implementing lazy initialization: Static variables can be used to implement lazy initialization, which is a technique for delaying the initialization of a variable until it is first used.

Here is an example of a static variable declared in a function:

#include <iostream>
using namespace std;

void fun()
{
    static int x = 0;
    x++;
    cout << x << endl;
}

int main()
{
    fun();
    fun();
    return 0;
}

This code is a C++ program that defines a function called fun() and then calls it twice from the main() function. The fun() function declares a static variable called x and increments it each time it is called. The function then prints the value of x to the console.

Because x is a static variable, its value is preserved between function calls. This means that when the fun() function is called the second time, the value of x will be 1, not 0. Therefore, the output of the program will be as follows:

1
2

This code demonstrates how static variables can be used to store state information that needs to be accessed by multiple function calls.

Aliasing & Constant Variable

Aliasing

Aliasing in C++ is when two or more different names refer to the same memory location. This can happen when you use pointers or references, or when you declare two variables of the same type and initialize them to the same value.

For example, the following code creates an alias to the variable x:

int x = 1;
int &y = x;

Now, both the variables x and y refer to the same memory location. If you change the value of x, the value of y will also change.

Example:

#include <iostream>
using namespace std;

int main()
{
    int x = 1;
    int &y = x;
    x = 5;
    int &z = y;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = 7;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;
    y = x + z - 3;
    cout << "x = " << x << " " << "y = " << y << " " << "z = " << z << endl;

    return 0;
}

The code begins by declaring an integer variable named x and initializing it to 1. Then, it declares an integer reference named y and binds it to the variable x. This means that y is now an alias for x.

Next, the code assigns the value 5 to the variable x. This also changes the value of the variable y, since it is an alias for x.

Then, the code declares another integer reference named z and binds it to the variable y. This means that z is also an alias for x.

Now, all three variables x, y, and z refer to the same memory location. This means that changing the value of any one of these variables will also change the value of the other two variables.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 5 y = 5 z = 5

Next, the code assigns the value 7 to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 7 y = 7 z = 7

Finally, the code calculates the value of x + z - 3 and assigns it to the variable y. This also changes the values of the variables x and z, since they are all aliases for the same memory location.

The code then prints the values of the variables x, y, and z to the console. The output will be:

x = 11 y = 11 z = 11

This code demonstrates how aliasing can be used to change the values of multiple variables at once. It also demonstrates how aliasing can be used to create aliases for complex expressions.

It is important to note that aliasing can be a powerful tool, but it can also lead to confusion and errors if used incorrectly. It is important to carefully consider the implications of aliasing before using it in your code.

Constant Variable

A constant variable in C++ is a variable whose value cannot be changed after it is initialized. To declare a constant variable, you use the const keyword before the variable type. For example:

const double Pi = 3.14;

Once you have declared a constant variable, you cannot assign a new value to it. If you try to do so, the compiler will generate an error.

Example:

#include <iostream>
using namespace std;

int main()
{
    const double Pi = 3.14;
    int r;
    cout << "please enter r: ";
    cin >> r;
    double a = Pi * r * r;
    cout << "Area of circle = " << a << endl;

    return 0;
}

This code calculates the area of a circle. The program begins by declaring a constant double variable named Pi and initializing it to the value 3.14. Then, it declares an integer variable named r and prompts the user to enter a value for it.

Next, the program calculates the area of the circle using the following formula:

  • Area = πr²

The program then prints the area of the circle to the console.

Here is a breakdown of the code:

int main()
{
  // Declare a constant double variable named Pi and initialize it to the value 3.14.
  const double Pi = 3.14;

  // Declare an integer variable named r.
  int r;

  // Prompt the user to enter a value for r.
  cout << "please enter r: ";
  cin >> r;

  // Calculate the area of the circle.
  double a = Pi * r * r;

  // Print the area of the circle to the console.
  cout << "Area of circle = " << a << endl;

  return 0;
}

Output:

please enter r: 5
Area of circle = 78.5

Aliasing and constant variables can interact in a few interesting ways:

  • If you have a constant variable and you create an alias to it, the alias is also constant. This is because the alias is just another name for the same variable, and the value of the variable cannot be changed.
  • If you have a constant variable and you pass it to a function as a parameter, the function cannot change the value of the variable. This is because the function is only allowed to modify the local copy of the variable.
  • If you have a pointer to a constant variable, you can still use the pointer to dereference the variable and read its value. However, you cannot use the pointer to change the value of the variable.

Here is an example of aliasing and constant variables in C++:

#include <iostream>
using namespace std;

int main()
{
    int i = 1;
    int &j = i;
    cout << "j = " << j << endl;
    const int &k = j;
    cout << "k = " << k << endl;

    return 0;
}

Output:

j = 1
k = 1

 

One Dimensional Array (part 1)

An array is a data structure that stores a collection of elements of the same data type. These elements are stored in contiguous memory locations, and they can be accessed using an index. Arrays provide a way to manage and manipulate a large set of data efficiently.

In C++, you can declare an array by specifying its data type and the number of elements it will hold. Here’s a basic syntax:

data_type array_name[array_size];

Arrays in C++ are zero-indexed, meaning the first element is accessed using the index 0, the second element with index 1, and so on. You can access and modify array elements using square brackets:

array_name[index] = new_value;

Here is an example:

#include <iostream>
using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 20;
    cout << x[0] << endl;
    x[2];
    x[3];
    x[4];

    return 0;
}

1. int x[5];

This line declares an integer array named x with a size of 5. It means that x can store five integer values. However, at this point, the values in the array are uninitialized, which means they contain random data.
2. x[0] = 10;

Here, we assign the value 10 to the first element of the array x. In C++, arrays are zero-indexed, so x[0] refers to the first element.
3. x[1] = 20;

Similarly, we assign the value 20 to the second element of the array x, which is x[1].
4. cout << x[0] << endl;

This line prints the value of the first element of the array x, which is 10, to the console. It uses the cout object from the C++ Standard Library to output the value, followed by an end-of-line character (endl) for formatting.
5. x[2];

These lines appear to be accessing the third element of the array x, but they don’t do anything. It’s essentially a “noop” operation, and the value in x[2] remains uninitialized or unchanged.
6. x[3]; and x[4];

Similar to the previous line, these lines access the fourth and fifth elements of the array x, but they also don’t perform any meaningful operation.

Output:

10

Here is another example:

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    x[0] = 10;
    x[1] = 5;
    x[4] = x[0] + x[1];
    cout<< x[4] << endl;

    return 0;
}

Output:

15

Arrays only accept constant array size, Example:

#include <iostream>

using namespace std;

int main()
{
    const int t = 5;
    int x[t];

    return 0;
}

This code declares an integer array `x` with a size of 5, and the size is determined by the constant `t`, which is set to 5. The `const` keyword ensures that `t` cannot be changed later in the program. This code doesn’t perform any further operations on the array; it simply demonstrates how to declare an array with a size determined by a constant.

You can also declare the size of your array, and declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = { 1,4,8,7,2 };
    cout << x[0] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes it with the values 1, 4, 8, 7, and 2. It then prints the first element of the array, which is 1, to the console. This code demonstrates how to create an array and access its elements in C++.

But what if you declared no initial values into your array?

#include <iostream>

using namespace std;

int main()
{
    int x[5];
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 but does not initialize its elements. Therefore, when you attempt to print the value of the fourth element, it will display a random or garbage value. It’s important to initialize array elements before using them to avoid unpredictable behavior in your programs.

What if you declared only one initial value that equals to 0?

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {0};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes all its elements to 0. It then prints the value of the fourth element of the array, which is 0, to the console. This code demonstrates how to create an array with specific initial values in C++.

You can also declare a size of array and declare some of the first initial values, for example:

#include <iostream>

using namespace std;

int main()
{
    int x[5] = {1,2,3};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x with a size of 5 and initializes the first three elements with values, while the remaining two elements are automatically initialized to 0. It then prints the value of the fourth element, which is 0, to the console.

Or, you can declare no size of your array and only declare the initial values of your array:

#include <iostream>

using namespace std;

int main()
{
    int x[] = {1,2,3,4,5};
    cout << x[3] << endl;

    return 0;
}

This code declares an integer array x and initializes it with values using an array initialization list. It then prints the value of the fourth element of the array, which is 4, to the console. This code demonstrates how to create an array and access its elements in C++.

How does the compiler store the values on an array?

The compiler stores the values of an array in contiguous memory locations. This means that the values of the array elements are stored next to each other in memory. The compiler allocates a block of memory that is large enough to store all of the array elements, and then it stores the values of the elements in this block of memory.

The compiler keeps track of the address of the first element in the array, and then it uses this address to access the other elements in the array. For example, to access the element at index i, the compiler adds i to the address of the first element.

The specific way that the compiler stores the values of an array depends on the data type of the array elements. For example, if the array elements are integers, the compiler will store each integer in a single memory location. However, if the array elements are structs, the compiler will store each struct in a contiguous block of memory locations.

This code shows you how to read and store user input in an array in C++, it allows the user to input an integer value for the first element of an array, arr[0], and then it displays the value that was entered.

#include <iostream>

using namespace std;

int main()
{
    int arr[50];
    cout << "Enter arr[0]: " << endl;
    cin >> arr[0];
    cout << arr[0] << endl;

    return 0;
}

 

To traverse the elements of an array, you can use loops like for or while. Looping through an array allows you to perform operations on each element systematically.

Example:

#include <iostream>

using namespace std;

int main()
{
    int arr[10];
    for (size_t i = 0; i < 10; i++)
    {
        cout << "Enter arr[" << i << "]: ";
        cin >> arr[i];
    }
    for (size_t i = 0; i < 10; i++)
    {
        cout << "arr[" << i << "] = " << arr[i] << endl;
    }

    return 0;
}

This code allows the user to input 10 integer values, one for each element of the array, and then it displays the values along with their indices. It demonstrates how to read and store multiple user inputs in an array and subsequently print the contents of the array in C++.

One Dimensional Array (part 2)

Arrays are incredibly versatile, and you can perform various operations on them, such as copying the initial values of an existing array into another one.

Of course we cannot use the following command:

arr2 = arr1;

Because we aren’t assigning a single value. Each array has a collection of values, so if we need to assign a single value in an array we have to specify its index:

arr2[0] = arr1[0];

But what if we need to assign all the values of an array into another array?

Example 1:

#include <iostream>

using namespace std;

int main()
{
    const int s = 4;
    int arr1[s] = { 10,20,30,40 };
    int arr2[s];

    for (size_t i = 0; i <= s-1; i++)
    {
        arr2[i] = arr1[i];
    }

    for (size_t i = 0; i < s; i++)
    {
        cout << arr2[i] << " ";
    }
    cout << endl;

    return 0;
}

This code initializes an array arr1 with values, then copies the contents of arr1 into another array arr2. Finally, it prints the elements of arr2. This demonstrates how to copy the contents of one array into another in C++.

Output:

10 20 30 40

Example 2:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,0 };
    int sum = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        //sum += arr[i];
        sum = sum + arr[i];
    }
    cout << "sum = " << sum << endl;

    return 0;
}

This code calculates the sum of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate values.

Output:

sum = 1000

Example 3:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,500,100 };
    long long d = 1;
    
    for (size_t i = 0; i < s; i++)
    {
        d *= arr[i];
    }
    cout << "multi = " << d << endl;

    return 0;
}
  • long long d = 1; :This line initializes a long long integer variable d to 1. This variable will be used to accumulate the product of the elements in the array.
  • long long is a data type in C++ that represents a 64-bit integer. It’s designed to store very large integer values. It can hold a wider range of values compared to regular int or long integers.
  • So, the statement long long d = 1; declares a variable named d with a data type of long long and initializes it with the value 1. This variable can then be used to store and manipulate large integer values in your program.

In summary, this code calculates the product of the elements in the integer array arr and then prints the result to the console. It demonstrates how to use a loop to iterate through an array and accumulate the product of its elements.

Output:

multi = 200000000000

Example 4:

#include <iostream>

using namespace std;

int main()
{
    const int s = 5;
    int arr[s] = { 100,200,200,501,101 };
    int sumEven, sumOdd = 0;
    
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] % 2 == 0)
            sumEven += arr[i];
        else
            sumOdd += arr[i];
    }
    cout << "Sum of even numbers = " << sumEven << endl;
    cout << "Sum of odd numbers = " << sumOdd << endl;

    return 0;
}

This code calculates the sum of even and odd numbers separately in the integer array arr and then prints the results to the console.

Output:

Sum of even numbers = 500
Sum of odd numbers = 602

Example 5:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int marks[s] = { 100,99,98,88,70,90 };
    int sum = 0;
    for (size_t i = 0; i < s; i++)
    {
        sum += marks[i];
    }
    cout << "Average = " << sum / s << endl;

    return 0;
}

This code calculates the average of the marks stored in the integer array marks and then prints the average to the console.

Output:

Average = 90

Example 6:

#include <iostream>

using namespace std;

int main()
{
    const int s = 6;
    int arr[s] = { 22,100,95,101,200,90 };
    int max = 0;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] > max)
            max = arr[i];
    }
    cout << "Maximum number = " << max << endl;

    return 0;
}

This code finds the maximum value among the numbers stored in the integer array arr and then prints the maximum value to the console.

Output:

Maximum number = 200

Example 7:

#include <iostream>

using namespace std;

int main()
{
    int vector[5];
    cout << "Enter 5 numbers: ";
    for (int i = 0; i < 5; i++)
        cin >> vector[i];
    cout << endl;
    
    int Element;
    cout << "What is the element you are looking for? ";
    cin >> Element;
    
    bool Found = false;
    int i;
    for (i = 0; i < 5; i++)
        if (Element == vector[i])
        {
            Found = true;
            break;
        }
    cout << endl;
    if (Found)
        cout << Element << " found at position " << i << endl;
    else
        cout << Element << " is not in this array!" << endl;

    return 0;
}

In this C++ code, you’re taking user input to populate an integer array `vector` of size 5 and then searching for a specific element within the array. Let’s break down the code step by step:

  1. int vector[5];
    – This line declares an integer array `vector` with a size of 5, which can store up to five integer values.
  2. Input Loop to Populate the Array:
    – The code prompts the user to enter five numbers and stores them in the `vector` array using a `for` loop that iterates five times. Each input is assigned to a different element of the array.
  3. int Element;
    – This line declares an integer variable `Element`, which will store the value the user is searching for.
  4. Prompt for the Element to Search:
    – The code asks the user to input the element they want to search for.
  5. Search Loop:
    – The `for` loop is used to search for the element within the array. If the element is found, the loop breaks, and the `Found` flag is set to `true`. The variable `i` keeps track of the position where the element was found.
  6. Output the Result:
    – The code then checks if the element was found (i.e., `Found` is `true`). If found, it displays the element and its position in the array. If not found, it informs the user that the element is not in the array.

In summary, this code allows the user to enter five numbers into an array and then search for a specific element within the array. It provides feedback on whether the element was found and its position in the array.

One Dimensional Array part 3 (Passing Array To Function)

In C++, you can pass an array to a function, and this is a fundamental concept when working with arrays. When you pass an array to a function, you’re essentially allowing that function to operate on the array’s elements or modify the array if needed.

Here’s an explanation of how to pass an array to a function in C++:

Array Declaration in a Function

Array Parameters: To pass an array to a function, you need to declare the function parameter as an array. You can declare it in two ways:

  • Using a Fixed Size: If you know the size of the array in advance, you can specify the size in the function parameter, like this:
void functionName(int arr[5]) {
    // Code to work with the array
}
  • Using a Pointer: You can also declare the function parameter as a pointer to the array’s elements without specifying the size, like this:
void functionName(int *arr, int size) {
    // Code to work with the array
}

In this case, you pass the size of the array as a separate argument.

Passing the Array to the Function

Calling the Function: When you call the function, you provide the array as an argument. If you declared the function parameter with a fixed size, you pass the array directly. If you used a pointer, you pass the array and its size as arguments.

Example with a fixed-size array parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray);

Example with a pointer parameter:

int myArray[5] = {1, 2, 3, 4, 5};
functionName(myArray, 5);

Using the Array in the Function

Working with the Array: Inside the function, you can access and manipulate the elements of the array as needed. You can use array indices (e.g., arr[0], arr[1]) to access individual elements, and you can use loops to iterate through the elements.

Example of accessing array elements:

void functionName(int arr[5]) {
    for (int i = 0; i < 5; i++) {
        // Access and manipulate arr[i]
    }
}

Here is a demonstration of passing an array to functions for setting values in the array and then printing those values:

#include <iostream>
using namespace std;

void set(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << "Enter array value: ";
        cin >> arr[i];
    }
}

void print(int arr[], int s)
{
    for (size_t i = 0; i < s; i++)
    {
        cout << arr[i] << " ";
    }
}

int main()
{
    int a[5];
    set(a, 5);
    print(a, 5);

    return 0;
}

The set function allows the user to set values in the array, and the print function prints the values stored in the array. It’s a practical example of how to work with arrays and functions in C++.

Modifying the Array

Example 1:

This code shows an implementation of the “Bubble Sort” algorithm. Bubble Sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, indicating that the list is sorted. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

int main()
{
    int vector[] = {6,5,4,1,2};
    int t = 0;
    
    // Bubble Sort algorithm
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (vector[j] > vector[j + 1])
            {
                t = vector[j];
                vector[j] = vector[j + 1];
                vector[j + 1] = t;   
            }
        }
    }
    
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }

    return 0;
}
  1. int vector[] = {6, 5, 4, 1, 2};:
    An integer array vector is initialized with unsorted values.
  2. int t = 0;:
    An integer variable t is declared to be used for swapping elements during the sorting process.
  3. Bubble Sort Algorithm:
    The nested for loops are used to implement the Bubble Sort algorithm. The outer loop (i) controls the number of passes, and the inner loop (j) compares adjacent elements and swaps them if they are out of order.
  4. If the element at index j is greater than the element at index j + 1, a swap is performed to put them in ascending order.
  5. Printing the Sorted Array:
    After sorting is complete, the code uses a for loop to print the sorted elements in ascending order.

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array. Bubble Sort is not the most efficient sorting algorithm for large data sets, but it’s easy to understand and implement.

Example 2:

This code performs the sorting of an integer array using the Bubble Sort algorithm. It sorts the array in ascending order and then prints the sorted values. Let’s break down the code step by step:

#include <iostream>
using namespace std;

const int s = 5;
void sort(int arr[])
{
    int t = 0;
    for (size_t i = 0; i < 5 - 1; i++)
    {
        for (size_t j = 0; j < 5 - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;   
            }
        }
    }
}

void print(int vector[])
{
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << endl;
    }
}

int main()
{
    int vector[] = {0,-1,55,-5,-100};
    sort(vector);
    print(vector);
    return 0;
}

The output of this code will be the sorted array in ascending order, which is the result of applying the Bubble Sort algorithm to the initial unsorted array.

Example 3:

This code demonstrates how to reverse the elements of an integer array using a reversArray function. It reverses the array in-place and then prints the reversed array:

#include <iostream>
using namespace std;

void reversArray(int arr[], int s)
{
    for (size_t i = 0; i < s / 2; i++)
    {
        swap(arr[i], arr[s - i - 1]);
    }
}

int main()
{
    int vector[] = {3,2,4,5,6};
    reversArray(vector, 5);
    for (size_t i = 0; i < 5; i++)
    {
        cout << vector[i] << " ";
    }

    return 0;
}

The output of this code will be the reversed array, where the elements are reversed in place. This is achieved by swapping the first element with the last element, the second element with the second-to-last element, and so on. It’s a simple and efficient way to reverse the order of elements in an array.

 

Note:

If you don’t want to modify your array you can initial its value as a constant in the function. Example:

void print(const int arr[], int s)
{
    //body of the function
}

This way any try to modify the array will produce an error.

One Dimensional Array part4 (Array Of Character)

An array of characters in C++ is often referred to as a “string.” It is a fundamental data structure used to store sequences of characters, such as words, sentences, or even individual characters. In C++, strings are represented as arrays of characters, terminated by a special null character, ‘\0’, which indicates the end of the string.

to initiate a character we use a single quotation like this ‘L’.

Example 1:

char ch[5] = { 'a','b','c','d','e','\0' };

The null character (‘\0’), NULL or 0, is used to indicate the end of the string. This character is automatically added to the end of string literals and is crucial for various string manipulation functions.

If you add characters after the null character they won’t be read by the program.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    char ch[5];
    cin >> ch;
    cout << ch << endl;
    return 0;
}

This code reads a sequence of characters into a char array and then prints the array. However, there are a few things to note about potential issues and improvements in the code:

  1. Array Size:
    The char array ch has a size of 5. If you enter more than 4 characters, it will result in a buffer overflow, causing undefined behavior. It’s essential to ensure that the input doesn’t exceed the array size.
  2. Input Method:
    When using cin >> ch, it reads characters until it encounters whitespace. If you want to read an entire line (including spaces), you should use cin.getline(ch, size) or cin.get(ch, size).

Example 3:

#include <iostream>
using namespace std;

int main() {
    char ch[10];

    // Read up to 9 characters into the char array
    cin.get(ch, 10);

    // Output the char array
    cout << ch << endl;

    return 0;
}

This code reads up to 9 characters (plus the null terminator) into a char array using cin.get() and then prints the array.
Here are a few points to note:

  1. Array Size:
    The char array ch has a size of 10. Since cin.get() reads up to one less than the specified size (leaving space for the null terminator), it effectively reads up to 9 characters.
  2. Input Method:
    cin.get(ch, 10) reads characters until either 9 characters are read, the newline character is encountered, or the end of file is reached. It stops reading after reaching the specified number of characters or encountering one of these conditions.
  3. Null Terminator:
    The array is not explicitly null-terminated by cin.get(); however, C++ streams automatically append a null terminator at the end of the string when reading into a character array. Therefore, the array ch is effectively treated as a C-style string.

Output:

The cout << ch << endl; statement prints the contents of the char array, treating it as a null-terminated string. If fewer than 9 characters were entered, it prints the characters entered. If 9 characters were entered, it prints those 9 characters followed by the null terminator.

Input Limitation:

Keep in mind that the user input is limited to 9 characters, and exceeding this limit may lead to unexpected behavior. It’s essential to handle potential input overflows based on the specific requirements of your program.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char ch1[10], ch2[10];
    cin.getline(ch1, 10);
    cin.getline(ch2, 10);
    cout << ch1 << endl;
    cout << ch2 << endl;
    return 0;
}

This code reads two lines of input into separate char arrays and then prints each array on a new line.

Here are some points to note:

  1. Array Size:
    Both ch1 and ch2 are char arrays with a size of 10. The cin.getline() function reads characters until it encounters a newline character or reaches the specified size (leaving space for the null terminator).
  2. Input Limitation:
    The user input for each line is limited to 9 characters, and the null terminator is automatically added by cin.getline().
  3. Handling Spaces:
    Unlike cin >>, cin.getline() reads the entire line, including spaces. This allows you to input strings with spaces.

Output:

The cout << ch1 << endl; statement prints the contents of the first char array, treating it as a null-terminated string.
Similarly, cout << ch2 << endl; prints the contents of the second char array.
Newline Character:

Each call to cin.getline() reads until it encounters a newline character or reaches the specified size. The newline character is consumed but not stored in the arrays.
This code allows you to input two lines of text (up to 9 characters each) and then prints each line on a new line. It’s suitable for reading and displaying multiple lines of text, handling spaces, and avoiding buffer overflow issues.

 

There are some functions that are part of the C Standard Library and are used for manipulating C-style strings, which are arrays of characters. Here’s an explanation of each function:

  • strcpy (String Copy):

Description: The strcpy function is used to copy the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4];
    strcpy_s(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcpy_s Function:
    The strcpy_s function is part of the C Standard Library and is designed to provide safer string copying by including a size check.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes three characters for the content of ch1 (“AAA”) and one additional space for the null terminator (‘\0’).
  3. Safe String Copy:
    Unlike the standard strcpy function, strcpy_s requires you to provide the size of the destination array (destsz). It checks if there is enough space in the destination array to accommodate the source string and the null terminator. If there isn’t enough space, the function does not perform the copy and returns an error code.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2, which should be “AAA” in this case.

By using strcpy_s, you are taking steps to prevent buffer overflow issues that could occur if the destination array is not large enough to hold the contents of the source string. This is a good practice for enhancing the safety and robustness of your code.

  • strcat (String Concatenate):

Description: The strcat function is used to concatenate (append) the contents of one C-style string to another.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch1[] = "AAA";
    char ch2[4] = "HH";
    strcat(ch2, ch1);
    cout << ch2 << endl;
    return 0;
}
  1. strcat Function:
    The strcat function is part of the C Standard Library and is used to concatenate the contents of one C-style string to another.
  2. Buffer Size:
    The size of ch2 is explicitly specified as 4, which includes two characters (“HH”) and one additional space for the null terminator (‘\0’).
  3. Concatenation:
    The strcat(ch2, ch1); line appends the contents of ch1 to the end of ch2. It starts copying characters from the null terminator of ch2 to the end of ch1 until it encounters the null terminator of ch1. The null terminator of ch2 is updated accordingly.

Output:

The cout << ch2 << endl; statement outputs the contents of ch2 after the concatenation. Since the size of ch2 is limited to 4, it can hold “HH” and the null terminator, but only one additional character from ch1 (“A”) can be accommodated.
Result:

The output of this code is “HHA”, which is the result of concatenating “AAA” to the end of the existing content in ch2.
It’s important to ensure that the destination array has enough space to accommodate the concatenated string, and using functions like strcat requires careful management of buffer sizes to prevent buffer overflows.

  • strcmp (String Compare):

Description: The strcmp function is used to compare two C-style strings lexicographically.

The strcmp function returns an integer value indicating the lexicographic relationship between the two strings. It returns:
– 0 if the strings are equal,
– a negative value if str1 is lexicographically less than str2,
– a positive value if str1 is lexicographically greater than str2.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    cout << strcmp("abc", "abc") << endl;
    return 0;
}

Output:

The cout statement outputs the result of the comparison using strcmp. In this case, since the strings are equal, the output will be 0.

The strcmp function is commonly used for sorting strings, dictionary operations, and other scenarios where you need to determine the lexicographic order of strings. It’s important to handle the result appropriately based on your specific requirements in the program.

  • strlen (String Length):

Description: The strlen function is used to determine the length of a C-style string.

Example:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    char ch[] = "jjjjjjjjjjjjjjjjjjjjj";
    cout << strlen(ch) << endl;
    return 0;
}

Output:

The cout statement outputs the result of strlen(ch), which is the length of the string “jjjjjjjjjjjjjjjjjjjjj”. Since there are 21 characters in the string, the output will be 21.

The strlen function is useful for obtaining the length of strings, and it’s important to note that the length does not include the null terminator. Make sure that the string is properly null-terminated to get accurate results with strlen.

 

 

 

 

 

Two Dimensional Array

A two-dimensional array in C++ is a structure that allows you to store elements in a tabular form, organized in rows and columns. It is essentially an array of arrays.

Here’s an explanation of a two-dimensional array in C++:

  • Declaration and Initialization:
// Declaration of a 2D array
int matrix[3][4];

// Initialization of a 2D array
int anotherMatrix[2][3] = { {1, 2, 3}, {4, 5, 6} };
  • Structure:

In a 2D array, elements are arranged in rows and columns. The first index represents the row, and the second index represents the column.

  • Memory Representation:

In memory, a 2D array is stored in a contiguous block of memory. The elements of each row are stored together, and rows are stored one after the other.

  • Accessing Elements:
int value = matrix[1][2];  // Accessing the element in the second row and third column
  • Initialization with Nested Loops:

Common Operations:

– Iterating through elements using nested loops.
– Performing operations on each element.
– Passing a 2D array to functions.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int a[3][4];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 4; j++)
        {
            cin >> a[i][j];
        }
    }
    for (size_t r = 0; r < 3; r++)
    {
        for (size_t c = 0; c < 4; c++)
        {
            cout << a[r][c] << " ";
        }
        cout << endl;
    }
    return 0;
}

This code allows the user to input values into a 2D array a[3][4] and then prints the array in a tabular form.

Here are the key points:

  1. 2D Array Input:
    The nested loops (for loops) are used to iterate over each element of the 2D array and input values using cin.
  2. 2D Array Output:
    Another set of nested loops is used to iterate over each element of the 2D array and output the values using cout.
    The inner loop prints each row, and the outer loop moves to the next row, creating a tabular form.
  3. Tabular Output:
    The cout << a[r][c] << ” “; statement prints each element of the 2D array followed by a space.
    The cout << endl; statement is used to move to the next line after printing each row.
  4. User Interaction:
    The user is prompted to input values for each element of the 2D array. The input is expected to be provided in a row-wise fashion.
  5. Array Size:
    The array a is declared with 3 rows and 4 columns, creating a 3×4 matrix.

This code allows the user to interactively input values into a 3×4 2D array and then displays the array in a tabular format.

Example 2:

#include <iostream>
using namespace std;

int main() {
    // Initialization of a 2D array with predefined values
    int arr[2][4] = {{1, 1, 1, 1}, {2, 2, 2, 2}};
    
    // Variable to store the sum of array elements
    int sum = 0;

    // Nested loops to iterate over each element of the 2D array
    for (size_t r = 0; r < 2; r++) {
        for (size_t c = 0; c < 4; c++) {
            // Accumulate the values to calculate the sum
            sum += arr[r][c];
        }
    }

    // Output the sum of array elements
    cout << "sum = " << sum << endl;

    return 0;
}

Output:

In this specific example, the sum is calculated as follows: 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 = 12.
The output will be sum = 12.

This code is a simple illustration of how to iterate over elements in a 2D array and perform a basic operation, in this case, calculating the sum of all elements.

Example 3:

#include <iostream>
using namespace std;
int main()
{
    int marks[10][5];
    for (size_t r = 0; r < 10; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            cout << "Enter mark " << c + 1 << " " << "for student " << r + 1 << ": " << endl;
            cin >> marks[r][c];
        }
    }
    double s = 0;
    float avg[10];
    for (size_t r = 0; r < 10; r++)
    {
        s = 0;
        for (size_t c = 0; c < 5; c++)
        {
            s += marks[r][c];
        }
        avg[r] = s / 5;
        cout << "Average for student #" << r + 1 << " = "<< avg[r] << endl;
    }
    return 0;
}

This code collects marks for 10 students in 5 subjects, calculates the average mark for each student, and then outputs the average for each student.

Example 4:

#include <iostream>
using namespace std;
int main()
{
    char MTXchar[5][5] = {{'*','$','$','$','$'},
                          {'$','*','$','$','$'},
                          {'$','$','*','$','$'},
                          {'$','$','$','*','$'},
                          {'$','$','$','$','*'}};
                          
    for (size_t r = 0; r < 5; r++)
    {
        for (size_t c = 0; c < 5; c++)
        {
            
            if (c == r)
                cout << MTXchar[r][c];
            else
                cout << " ";
        }
        cout << endl;
    }
    return 0;
}

This code defines a 5×5 matrix (MTXchar) containing ” characters on the main diagonal and ‘$’ characters elsewhere. It then prints only the characters on the main diagonal, resulting in a diagonal line of ” characters.

Output:

The code outputs a diagonal line of ‘*’ characters on the console.

*    
 *   
  *  
   * 
    *

 

Passing a two-dimensional array to a function in C++ involves specifying the array as a parameter in the function declaration. Since a 2D array is essentially an array of arrays, you need to specify the size of the columns (since the rows are implicitly known based on the number of arrays).

  • Function Declaration:

When declaring a function that accepts a 2D array, you need to specify the array parameter along with the size of the columns. The size of the rows is not explicitly specified.

void functionName(int arr[][COLS], size_t rows, size_t cols) {
    // Function logic using arr
}

– int arr[][COLS]: This syntax indicates that the function takes a 2D array of integers with a specified number of columns (COLS).
– size_t rows: This parameter can be used to pass the number of rows in the array.
– size_t cols: This parameter can be used to pass the number of columns in the array

  • Function Call:

When calling the function, you need to provide the actual 2D array along with the number of rows and columns.

int myArray[ROWS][COLS];
functionName(myArray, ROWS, COLS);

– myArray: The name of the 2D array you want to pass.
– ROWS: The number of rows in the array.
– COLS: The number of columns in the array.

Example 5:

#include <iostream>
using namespace std;
void f(int arr[][5], int r)
{
    for (size_t i = 0; i < r; i++)
    {
        for (size_t j = 0; j < 5; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int main()
{
    int a[2][5] = {1,2,3,4,5,
                   10,20,30,40,50};
    f(a, 2);
    return 0;
}

The function f takes a 2D array (arr) and its number of rows (r) as parameters.
It uses nested loops to iterate over each element of the array and prints the elements in a tabular form.

The main function calls the function f with the 2D array a and the number of rows (2) as arguments.

Output:

The output of this code would be the elements of the 2D array a printed in a tabular form.

The printed output would look like:

1 2 3 4 5 
10 20 30 40 50 
  • Transpose matrix

The transpose of a matrix is an operation that flips the matrix over its diagonal, switching the row and column indices of the matrix. In other words, if the original matrix has elements at position (i, j), the transposed matrix will have the element at position (j, i).

Example 6:

#include <iostream>
using namespace std;
int main()
{
    int arr[3][3];
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cin >> arr[i][j];
        }
    }
    cout << "Matrix is: \n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    cout << "Transpose matrix is:\n";
    for (size_t i = 0; i < 3; i++)
    {
        for (size_t j = 0; j < 3; j++)
        {
            cout << arr[j][i] << " ";
        }
        cout << endl;
    }

    return 0;
}

This code takes user input for a 3×3 matrix, prints the original matrix, and then prints its transpose.

Here are the key points:

  1. Input:
    The nested loops take user input for a 3×3 matrix.
  2. Original Matrix Output:
    After taking input, the code outputs the original matrix.
  3. Transpose Matrix Output:
    Another set of nested loops outputs the transpose of the matrix. It switches the row and column indices.

Example Output:

If the user enters:

1 2 3
1 2 3
1 2 3

The output would be:

Matrix is: 
1 2 3 
1 2 3 
1 2 3 
Transpose matrix is:
1 1 1 
2 2 2 
3 3 3

 

Pointer

In C++, a pointer is a variable that stores the memory address of another variable. Pointers provide a powerful mechanism for working with memory and data structures. They allow direct manipulation of memory addresses and enable efficient memory management.

Declaring Pointers

To declare a pointer, you use the data type followed by an asterisk (*) and the pointer name. For example:

int *ptr; // Declares a pointer to an integer
double *dblPtr; // Declares a pointer to a double

Initializing Pointers

Pointers should be initialized before use. You can initialize a pointer by assigning the address of a variable to it. The address-of operator (&) is used to obtain the memory address of a variable.

int num = 10;
int *ptr = &num; // Initializes ptr with the address of num

Dereferencing Pointers

Dereferencing a pointer means accessing the value stored at the memory address it points to. The dereference operator (*) is used for this purpose.

int num = 10;
int *ptr = &num;

cout << *ptr; // Prints the value stored at the address pointed by ptr

Example 1:

#include <iostream>
using namespace std;

int main() {
    // Declaration of a pointer to an integer
    int *ptr;

    // Declaration and initialization of an integer variable
    int val = 5;

    // Assigning the address of 'val' to the pointer 'ptr'
    ptr = &val;

    // Printing the address stored in the pointer
    cout << ptr << endl;

    // Printing the value stored at the address pointed by 'ptr'
    cout << *ptr << endl;

    // Return 0 to indicate successful execution
    return 0;
}

This code declares a pointer, initializes an integer variable, assigns the address of that variable to the pointer, and then prints both the pointer’s value (memory address) and the value it points to.

Here are the key points:

  1. Pointer Declaration:
    int *ptr;: Declares a pointer to an integer. This pointer is currently uninitialized.
  2. Variable Declaration and Initialization:
    int val = 5;: Declares an integer variable named val and initializes it with the value 5.
  3. Assigning Address to Pointer:
    ptr = &val;: Assigns the memory address of the variable val to the pointer ptr. Now ptr “points” to the memory location of val.
  4. Printing Pointer’s Value (Memory Address):
    cout << ptr << endl;: Prints the memory address stored in the pointer ptr. The address is typically represented in hexadecimal format.
  5. Printing Value at the Address Pointed by Pointer:
    cout << *ptr << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by ptr. Prints the value stored in the variable val.

Output:
If you run this program, the output will be something like:

0x7ffee3c86a4c   // The memory address (this will vary on each run)
5                // The value stored at the memory address

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int *p;
    int v = 9;
    p = &v;
    cout << *p << endl;
    return 0;
}

This code prints the address of the value pointed to by the pointer p using the expressions &*p.

cout << &*p << endl;: Uses the dereference operator (*) to access the value stored at the memory address pointed by p. The & operator then takes the address of this value. Essentially, &*p is equivalent to just p, so this line prints the memory address stored in the pointer p.

 

Pointer part 2 (Array vs Pointer & Passing Pointer To Function)

Arrays in C++

An array is a collection of elements of the same type stored in contiguous memory locations. In C++, arrays can be of primitive types (int, float, etc.) or user-defined types (structures, classes). Arrays have a fixed size, and the elements are accessed using an index.

int numbers[5] = {1, 2, 3, 4, 5};

Pointers in C++

A pointer is a variable that stores the memory address of another variable. Pointers allow for dynamic memory allocation and manipulation. They are often used for efficient memory management and for accessing elements in arrays.

int x = 10;
int *ptr = &x; // ptr now holds the address of x

Array vs. Pointer

In many contexts, arrays and pointers in C++ exhibit similar behavior. When an array name is used in an expression, it decays into a pointer to its first element. For example:

int arr[3] = {1, 2, 3};
int *ptr = arr; // Equivalent to &arr[0]

However, there are differences:

  • An array variable cannot be reassigned to point to a different memory location, whereas a pointer can.
  • Arrays carry information about their size, while pointers do not inherently know the size of the memory they point to.
  • Arrays can be used with the sizeof operator to determine their size, but pointers alone cannot.

Pointer Arithmetic

Pointers can be incremented or decremented to navigate through an array or block of memory.

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;

cout << *ptr; // Prints the first element (1)
ptr++;        // Moves to the next element
cout << *ptr; // Prints the second element (2)

 

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    for (size_t i = 0; i < 7; i++)
    {
        cout << *(arr + i) << endl;
    }
    return 0;
}

code prints the elements of an array using pointer arithmetic.

cout << *(arr + i) << endl;: Utilizes pointer arithmetic to access each element of the array. The expression arr + i calculates the memory address of the i-th element, and *(arr + i) dereferences the pointer to access the value stored at that address.

Output:
If you run this program, the output will be:

11
22
33
44
55
66
77

 

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[7] = {11,22,33,44,55,66,77};
    int *ptr;
    ptr = arr;
    for (size_t i = 0; i < 7; i++)
    {
        cout << *ptr << " ";
        ptr++;
    }
    return 0;
}

This code accomplishes the same goal as the previous example but uses a pointer (ptr) and pointer arithmetic to iterate through the array.

Output:
If you run this program, the output will be:

11 22 33 44 55 66 77

Passing Pointers to Functions

When passing an array to a function, you are actually passing a pointer to the first element of the array. This is due to the array decaying into a pointer in function arguments.

Example 3:

This code demonstrates the usage of pointers and a function that modifies the value it points to.

#include <iostream>
using namespace std;
int fun(int *p)
{
    *p = *p + 1;
    return *p;
}
int main()
{
    int x = 1;
    int *ptr = &x;
    cout << fun(ptr) << endl;
    cout << x << endl;
    cout << fun(&x) << endl;
    cout << x << endl;
    return 0;
}

Key points:

  1. Function fun:
    int fun(int *p): Takes a pointer to an integer as a parameter.
    *p = *p + 1;: Increments the value pointed to by the pointer.
    return *p;: Returns the updated value.
  2. Main Function:
    int x = 1;: Declares and initializes an integer variable x.
    int *ptr = &x;: Declares a pointer ptr and assigns the address of x to it.
    cout << fun(ptr) << endl;: Calls the function fun with the pointer ptr and prints the result. The value of x is now 2.
    cout << x << endl;: Prints the current value of x after the function call. It is now 2.
    cout << fun(&x) << endl;: Calls the function fun with the address of x directly and prints the result.
    The value of x is now 3.cout << x << endl;: Prints the final value of x. It is now 3.

Output:
If you run this program, the output will be:

2
2
3
3

 

Data Structures (struct)

In the world of programming, data structures play a pivotal role in how we organize and manipulate data efficiently. They act as the building blocks that enable us to create well-structured and organized programs. In this explanation, we will delve into one fundamental data structure in C++ known as struct.

What is a Data Structure?

Before we explore struct, let’s define what a data structure is. A data structure is a way of organizing and storing data in a computer’s memory to perform operations on that data more efficiently. It provides a blueprint for the storage and retrieval of information.

Introduction to struct in C++

struct in C++ is a user-defined data type that allows you to group together variables of different data types under a single name. Think of it as creating a custom data type tailored to the specific needs of your program. This makes your code more modular, organized, and easier to understand.

Syntax of struct:

The syntax for defining a struct is straightforward:

struct MyStruct

struct MyStruct

Example 1:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x;
    x.name = "Rolls-Royce";
    x.color = "Red";
    x.model = 2019;
    x.maxSpeed = 270;
    
    cout << x.name << endl;
    return 0;
}

code defines a struct named car that represents information about a car, and it creates an instance of this struct called x to store details about a specific car.

Key points:

  • Struct Definition (car):
    The struct named car has four member variables: name, color, maxSpeed, and model. These variables store information about a car.
  • Instance Creation (x):
    An instance of the car struct named x is created in the main function. This instance can store information about a specific car.
  • Assigning Values:
    Values are assigned to the member variables of the x instance using the dot (.) notation. For example, x.name = “Rolls-Royce” assigns the name “Rolls-Royce” to the name member variable.
  • Printing Information:
    The program prints the name of the car using cout << x.name << endl;. In this case, it will output “Rolls-Royce” to the console.

Output:
If you run this program, the output will be:

Rolls-Royce

Example 2:

Here is another way of initialization the values based on the previous example:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    cout << x.maxSpeed << endl;
    return 0;
}

Output:

250

Example 3:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = x;
    cout << y.name << endl;
    return 0;
}

Instance Creation and Initialization (x and y):

  • An instance of the car struct named x is created with initial values.
  • Another instance named y is created and initialized with the values of x. This is a memberwise copy, and each member of y gets the value of the corresponding member in x.

Example 4:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
}y;
int main()
{
    car x = {"BMW","Blue",250,2016};
    car y = {"Mercedes","Red",300,2016};
    if (x.maxSpeed > y.maxSpeed)
        cout << "car x is faster than car y";
    else
        cout << "car y is faster than car x";
    return 0;
}
  • Global Instance Declaration (y):
    An instance of the car struct named y is declared at the global scope. This means it can be accessed throughout the program.
  • Instance Creation and Initialization (x and Local y):
    – A local instance of the car struct named x is created with initial values.
    – Another local instance named y is created with different values. This y is local to the main function and shadows the global y within this scope.
  • Comparison and Output:
    The program compares the maximum speeds of cars x and y and prints a message indicating which car is faster.

Output:
If you run this program, the output will depend on the values assigned to maxSpeed in x and y. For the provided values, it will output:

car y is faster than car x

Pass ‘struct’ into function:

Example 5:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
void f(car f)
{
    cout << "Name = " << f.name << endl;
    cout << "Color = " << f.color << endl;
}
int main()
{
    car v = {"No name","Red",160,2000};
    f(v);
    return 0;
}

Key points:

  • Function Definition (f):
    The function f takes a car as a parameter and prints information about the car, specifically the name and color.
  • Instance Creation and Initialization (v):
    An instance of the car struct named v is created with initial values.
  • Function Call (f(v)):
    The program calls the function f with the v instance as an argument.

Output:
If you run this program, the output will be:

Name = No name
Color = Red

Example 6:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
};
car read_return(car&s)
{
    cout << "Enter car name:\n";
    cin >> s.name;
    cout << "Enter car color:\n";
    cin >> s.color;
    cout << "Enter car maximum speed:\n";
    cin >> s.maxSpeed;
    cout << "Enter car model:\n";
    cin >> s.model;
    return s;
}
int main()
{
    car v;
    read_return(v);
    car h;
    h = v;
    cout << h.name << endl;
    return 0;
}

Key points:

  • Function Definition (read_return):
    The function read_return takes a car reference as a parameter, reads input to populate its fields, and returns the modified car struct.
  • Function Call (read_return(v)):
    The program calls the function read_return with the v instance as a reference, allowing the function to modify the values of v.
  • Assignment and Printing:
    – The values of v are assigned to h.
    – The program prints the name of h.

Output:
If you run this program and enter values when prompted, the output will depend on the input provided. For example:

Enter car name:
BMW
Enter car color:
Blue
Enter car maximum speed:
250
Enter car model:
2022
BMW

Example 7:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car v = {"Kia"};
    v.fun(v);
    return 0;
}

Key points:

  • Member Function Definition (fun):
    The member function fun is defined inside the car struct.
    It takes a car as a parameter and prints its name.

Output:
If you run this program, the output will be:

Kia

Example 8:

#include <iostream>
#include <string>
using namespace std;
struct car
{
    string name;
    string color;
    int maxSpeed;
    int model;
    void fun(car n)
    {
        cout << n.name << endl;
    }
};

int main()
{
    car*h;
    car b = {"Toyota","Red",170,2008};
    h = &b;
    cout << h->color << endl;
    return 0;
}

Key points:

  • Pointer Declaration and Initialization (h):
    A pointer to a car named h is declared.
  • Instance Creation and Initialization (b):
    An instance of the car struct named b is created and initialized with specific values.
  • Pointer Assignment (h = &b):
    The address of b is assigned to the pointer h.
  • Pointer Dereferencing (h->color):
    The program prints the color of the car pointed to by h using the arrow operator (->).

Output:
If you run this program, the output will be:

Red

 

String

In C++, a string is a sequence of characters represented using the string class. Unlike C-style strings, which are arrays of characters, C++ strings are dynamic and provide a higher level of abstraction. The string class is part of the C++ Standard Template Library (STL), making it convenient and powerful for handling strings.

Declaring and Initializing Strings:

You can declare a string using the string keyword and initialize it in various ways:

// Declare and initialize strings
string str1 = "Hello, ";  // Initialization using a string literal
string str2("world!");    // Initialization using a constructor

// Concatenate strings
string result = str1 + str2;

When you use a string in C++, you must include its library this way:

#include <string>

Example:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string x = "Ahmad", y;
    y.assign(x);
    cout << "y = " << y << endl;

    return 0;
}

String Assignment:

  • string y;: Declares another string variable y.
  • y.assign(x);: Uses the assign method to copy the contents of string x to string y.

Output:

y = Ahmad

String Methods in C++:

Below is an explanation of various string methods in C++, along with their parameters and examples:

  1. at Method:
    Description: Returns the character at a specified position in the string.
    Parameters: Takes an index as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.at(0) << endl;
    
    // A
  2. length Method:
    Description: Returns the number of characters in the string.
    Parameters: No parameters.
    Example:

     string x = "Ahmad";
     cout << x.length() << endl;
    
     // 5
  3. size Method:
    Description: Same as length, returns the number of characters in the string.
    Parameters: No parameters.
    Example:

    string x = "Ahmad";
    cout << x.size() << endl;
    
    // 5
  4. substr Method:
    Description: Returns a substring of the original string.
    Parameters: Takes starting index and length as parameters.
    Example:

    string x = "Ahmad";
    cout << x.substr(1,3) << endl;
    
    // hma
  5. swap Method:
    Description: Swaps the content of two strings.
    Parameters: Takes another string as a parameter.
    Example:

    string x = "Ahmad", y = "Ali";
    cout << x.swap(y) << endl;
    
    // Swaps the content of x and y
  6. find Method:
    Description: Finds the first occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.find('a') << endl;
    
    // 3
  7. rfind Method:
    Description: Finds the last occurrence of a substring in the string.
    Parameters: Takes a substring as a parameter.
    Example:

    string x = "Ahmad";
    cout << x.rfind('a') << endl;
    
    // 3
  8. erase Method:
    Description: Erases characters from the string.
    Parameters: Takes starting index and count as parameters.
    Example:

    string x = "Ahmad";
    cout << x.erase(0,3) << endl;
    
    // ad
  9. replace Method:
    Description: Replaces a portion of the string with another string.
    Parameters: Takes starting index, length, and replacement string as parameters.
    Example:

    string x = "Ahmad";
    cout << x.replace(1,4,"li") << endl;
    
    // Ali
  10. insert Method:
    Description: Inserts characters into the string.
    Parameters: Takes starting index and string to insert as parameters.
    Example:

    string x = "Ahmad";
    cout << x.insert(5," Ali") << endl;
    
    // Ahmad Ali

These are some commonly used string methods in C++. Remember to include the <string> header for using these methods.

Review Function

The Structure of C++ program

#include <iostream>
using namespace std;

int main()
{
    cout << "Welcome to OOP in C++" << endl;

    return 0;
}

Let’s break down the structure and purpose of each command line in the provided C++ code:

#include <iostream>

Structure: This line begins with the #include preprocessor directive, followed by the <iostream> header file enclosed in angle brackets.

Purpose: This line includes the Input/Output Stream Library (iostream), which is essential for performing input and output operations in C++. It provides functionalities like cin for input and cout for output.

using namespace std;

Structure: The using namespace std; line declares that the code will be using the std namespace.

Purpose: The std namespace contains the standard C++ library components, including the cout and endl used in the code. By including this line, you can use these components without explicitly specifying the namespace each time you use them.

int main()
{

Structure: This line marks the beginning of the main function, which is the entry point of every C++ program.

Purpose: The main function is where the program execution starts. It is required in every C++ program, and the code within the curly braces {} defines the body of the main function.

cout << "Welcome to OOP in C++" << endl;

Structure: This line uses the cout object to output the text “Welcome to OOP in C++” to the console. The << operator is used for streaming the text to the output.

Purpose: This line is responsible for displaying a welcome message on the console, indicating that the program is focused on Object-Oriented Programming (OOP) in C++.

    return 0;
}

Structure: The return 0; line signifies the end of the main function. The 0 is returned to the operating system, indicating that the program executed successfully.

Purpose: The return 0; line is a common way to indicate a successful termination of the program. The value 0 is typically returned to the operating system to signify that the program executed without errors.

Libraries in C++

In C++, a library is a collection of pre-compiled functions, classes, and procedures that can be used by a program. These libraries provide a set of functionalities that can be utilized to perform common tasks, ranging from basic input/output operations to complex mathematical computations. Libraries offer a way to modularize code, promote code reuse, and streamline development by providing ready-made solutions for various tasks.

Here are some key aspects of libraries in C++:

  1. Standard Template Library (STL):
    The C++ Standard Library, often referred to as the Standard Template Library (STL), is a core part of C++. It includes a wide range of generic algorithms (e.g., sorting, searching) and data structures (e.g., vectors, lists, maps) that are implemented using templates. The STL simplifies programming by providing efficient and generic solutions to common problems.
  2. Header Files:
    C++ libraries are typically distributed as header files (with the extension .h or .hpp) and implementation files (with the extension .cpp). Header files contain declarations of functions, classes, and other entities that can be used in your program, while the implementation files contain the actual code.
  3. IOStream Library:
    The iostream library is a fundamental part of the C++ Standard Library and provides functionality for input and output operations. It includes cin (for input) and cout (for output), among other stream classes. Here’s an example of using the iostream library:

    #include <iostream>
    
    int main() {
        std::cout << "Hello, C++!" << std::endl;
        return 0;
    }
    
  4. Math Library:
    The cmath library provides a set of mathematical functions, such as trigonometric, logarithmic, and exponential functions.
  5. User-Defined Libraries:
    Apart from the standard libraries, you can create your own libraries to encapsulate and organize your code. This involves creating header files that declare the functions and classes, and implementation files that define their behavior. You can then include your custom library in other C++ programs.

Function in C++

In the realm of programming, functions play a pivotal role in organizing code, enhancing reusability, and promoting a structured approach to problem-solving. In C++, a function is a self-contained unit of code designed to perform a specific task or achieve a particular objective. It encapsulates a set of instructions, allowing you to break down a complex program into smaller, more manageable pieces.

Key Concepts
1. Modularity:
Functions enable the decomposition of a program into smaller, more manageable modules. Each function handles a specific aspect of the overall functionality, promoting a modular and organized code structure.

2. Reusability:
Once a function is defined, it can be reused in different parts of the program or even in other programs. This promotes the “Don’t Repeat Yourself” (DRY) principle, saving both time and effort.

3. Abstraction:
Functions provide a level of abstraction, allowing you to focus on high-level functionality without getting bogged down by the implementation details. This abstraction enhances code readability and simplifies the debugging process.

4. Parameters and Return Values:
Functions can accept input parameters and return values, allowing for dynamic and interactive code. Parameters provide a way to pass information into a function, while return values allow functions to communicate results back to the calling code.

Basic Syntax
A typical C++ function follows this basic syntax:

returnType functionName(parameterType1 parameterName1, parameterType2 parameterName2, ...) {
    // Function body: Code to perform the desired task
    // Optionally, a return statement to provide a result back to the caller
}

Let’s break down the components:

returnType: Specifies the type of data the function will return (if any).
functionName: The unique identifier for the function.
parameters: Input values that the function receives.
functionBody: The set of instructions defining the function’s behavior.

Example 1:

#include <iostream>
using namespace std;
int sum(int x, int y)
{
    return x + y;
}

int main()
{
    cout << sum(10,20) << endl;
    return 0;
}

This C++ code is a simple program that calculates and displays the sum of two numbers.

  • Define a Sum Function:
int sum(int x, int y)
{
    return x + y;
}

This block of code creates a function called sum. It takes in two numbers (x and y) and gives back their sum.

  • Use the Sum Function in the Main Part:
int main()
{
    cout << sum(10, 20) << endl;
    return 0;
}

Here, the main part is like the director of the program. It says, “Hey, calculate the sum of 10 and 20 using the sum function, and show me the result on the screen.” The endl is like pressing Enter on the keyboard; it moves to the next line.

  • Run the Program:

When you run this program, it does the calculation (10 + 20) inside the sum function, then displays the result (30) on the screen. The return 0; part tells the computer that everything went well.

 

Of course, the user can enter the data to be calculated using cin, using this command:

cin >> x >> y;

This command can be located inside the main function, but it’s better to use it inside the function itself to have a cleaner code.
See the following example:

#include <iostream>

using namespace std;
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;

    return 0;
}

This code asks the user to input two numbers, adds them together, and then displays the result.

  • Define a Sum Function:
int sum(int x, int y)
{
    cout << "Enter two numbers:\n";
    cin >> x >> y;
    return x + y;
}

This block of code defines a function called sum. It asks the user to enter two numbers, reads those numbers from the keyboard (cin), and then returns the sum of those numbers.

  • Use the Sum Function in the Main Part:
int main()
{
    int x = 0, y = 0;
    int z = sum(x, y);
    cout << "The sum is = " << z << endl;
    return 0;
}

In the main part, it starts with x and y set to 0. It then calls the sum function, passing x and y as arguments. The sum function gets user input, adds the numbers, and returns the result. The result is stored in z. Finally, it displays the sum with a message using cout.

So, in a nutshell, this program is like a simple interactive calculator. It asks you for two numbers, adds them together, and then shows you the result on the screen.

Providing initial values to variables is crucial to avoid errors.

Example 2:

#include <iostream>
using namespace std;

double avg(double m1, double m2, double m3)
{
    return (m1 + m2 + m3) / 3;
}

int main()
{
    cout << avg(100, 60, 50);
    return 0;
}

This code calculates and displays the average of three numbers.

The avg function takes in three numbers (m1, m2, and m3), adds them together, divides by 3, and returns the result. This is how you calculate the average of three numbers.
In the main part, it directly calls the avg function with three numbers (100, 60, and 50) as arguments. It then uses cout to display the result, which is the average of these three numbers.

Example 3:

#include <iostream>
using namespace std;

int max(int n1, int n2, int n3)
{
    int m = n1;
    if (m < n2)
        m = n2;
    if (m < n3)
        m = n3;
    return m;
}

int main()
{
    cout << max(100, 20, 800);
    return 0;
}

This code finds and displays the maximum of three numbers.

The max function takes in three numbers (n1, n2, and n3) and uses conditional statements (if) to determine the maximum among them. It begins by considering n1 as the initial maximum value and then employs conditional statements (if) to compare it with the other values. Whenever the condition is met, the maximum value is updated. The maximum value is then returned.

In the main part, it directly calls the max function with three numbers (100, 20, and 800) as arguments. It then uses cout to display the result, which is the maximum of these three numbers.

We can find a minimum value among other values using the same logic but changing the conditions.

Example 4:

#include <iostream>
using namespace std;

void p()
{
    cout << "myName\n";
}

int main()
{
    p();
    return 0;
}

This code defines a function and then calls that function in the main part of the program.

The function called p used void keyword before the function name which means that this function doesn’t return any value. Inside the function, it uses cout to display the text “myName” on the screen.

In the main part, it calls the p function. When a function is called, the program jumps to that function, performs the tasks inside it, and then returns to where it was called. In this case, it jumps to the p function, prints “myName” to the screen, and then returns to the main function.

  • Now, let’s talk about the concept of a void function:

A void function is a function that doesn’t return a value. In this example, the p function is a void function because it has the void keyword before its name.

Void functions are useful when you want a function to perform a task or set of tasks without needing to provide a result back to the part of the program that called it.

Example 5:

#include <iostream>
using namespace std;

int mul(int x = 10, int y = 50)
{
    return x*y;
}

int main()
{
    cout << mul(10) << endl;
    cout << mul(10, 2) << endl;
    cout << mul() << endl;

    return 0;
}

This code demonstrates the use of default arguments in a function.

The function called mul multiplies two numbers (x and y). The interesting part is that both x and y have default values assigned (10 and 50, respectively). If these values are not provided when the function is called, these defaults will be used.

In the main part, it calls the mul function multiple times with different combinations of arguments:

mul(10): It uses the default value 50 for y, so it multiplies 10 by 50.
mul(10, 2): It uses both 10 and 2 provided as arguments, so it multiplies 10 by 2.
mul(): Since no arguments are provided, it uses both default values (10 and 50), so it multiplies 10 by 50.

  • Now, let’s talk about the concept of default arguments:

Default arguments allow you to provide values to parameters in a function declaration, so if the caller doesn’t provide values, the default values are used.

In this example, the mul function has default values for both x and y, making it flexible when calling the function with different numbers of arguments.

Example 6:

#include <iostream>
using namespace std;

void ref(int &x, int &y)
{
    x += 1;
    y += 1;
}

int main()
{
    int p = 0, t = 0;
    ref(p, t);
    cout << "p = " << p << endl;
    cout << "t = " << t << endl;
    return 0;
}

This code demonstrates the concept of “call by reference.”

The function called ref has an interesting part which is that it takes references (&x and &y) as parameters, indicating that it will directly modify the values of the variables passed to it.

In the main part, it declares two variables (p and t) and initializes them to 0. Then, it calls the ref function with p and t as arguments. Inside the ref function, both p and t are increased by 1. Finally, it prints the values of p and t after the function call using cout.

  • Now, let’s talk about the concept of call by reference:

In C++, when you pass parameters to a function by reference (using &), the function receives the memory addresses of the actual variables, not just copies of their values.

This means any changes made to the parameters inside the function directly affect the original variables outside the function.

In this example, the ref function modifies the values of p and t directly because they are passed by reference.

Built-in functions

Built-in functions in C++ are pre-defined functions provided by the C++ programming language. These functions are part of the standard C++ library and offer ready-made solutions for common tasks. They are designed to perform specific operations and can be used by programmers without the need to write the entire code for those operations.

Here’s a simple breakdown:

  • Ready-made Tools:
    Built-in functions are like tools that are already available for you to use. Instead of creating these tools from scratch, you can simply use the built-in functions to perform various tasks.
  • Part of the Standard C++ Library:
    These functions are part of the standard C++ library, which is a collection of tools and functionalities that come with every C++ compiler. You don’t need to create or install anything extra to use them.
  • Common Operations:
    Built-in functions are designed to perform common operations such as input/output, mathematical calculations, string manipulations, and more. Examples include cout and cin for printing and reading from the console, sqrt for square root, and strlen for getting the length of a string.
  • Saves Coding Time:
    By using built-in functions, you can save a lot of time and effort. You don’t need to write complex code for tasks that are already handled by these functions.
  • Consistency Across Platforms:
    Since these functions are part of the standard library, they provide a consistent way to perform operations across different platforms and compilers. This makes your code more portable and ensures it works similarly on various systems.

In essence, built-in functions in C++ are like a toolbox that comes with the language. They provide a set of tools you can use to make your programming tasks easier, faster, and more standardized. As you become more familiar with C++, you’ll discover and leverage these functions to streamline your code.

Here are some common built-in functions in C++:

  1. Input/Output Functions:
    cout: Used to display output to the console.
    cin: Used to take input from the user through the console.
  2. Mathematical Functions:
    sqrt(): Calculates the square root of a number.
    abs(): Returns the absolute value of a number.
    pow(): Raises a number to a specified power.
  3. String Functions:
    strlen(): Returns the length of a string.
    strcpy(): Copies one string to another.
    strcat(): Concatenates (joins) two strings.
  4. Character Functions:
    isalpha(): Checks if a character is an alphabet letter.
    isdigit(): Checks if a character is a digit.
    toupper(): Converts a character to uppercase.
  5. Array Functions:
    sizeof(): Returns the size of a data type or an array.
    sort(): Sorts elements in an array in ascending order.
  6. Memory Functions:
    malloc(): Allocates a specified amount of memory dynamically.
    free(): Releases memory that was previously allocated with malloc.
  7. Time and Date Functions:
    time(): Returns the current time in seconds.
    ctime(): Converts a time value into a string representation.

Example 7:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    cout << abs(-10) << endl;
    cout << max(10, 20) << endl;
    cout << max(max(10, 20), 30) << endl;
    int x = 10, y = 20;
    swap(x,y);
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    
    return 0;
}

This code demonstrates the usage of several built-in functions from the <cmath> and <algorithm> libraries.

  • abs(-10): Calculates the absolute value of -10 and prints the result (10) to the console.
  • max(10, 20): Finds the maximum of two numbers (10 and 20) and prints the result (20) to the console.
  • max(max(10, 20), 30): Compares three numbers (10, 20, and 30) and finds the maximum among them. It prints the result (30) to the console.
  • swap(x, y): Swaps the values of x and y. After this line, x will be 20, and y will be 10.

Output:

10
20
30
x = 20
y = 10

 

 

Review Arrays

What is an Array?

An array is a fundamental data structure in C++ that allows you to store multiple elements of the same data type under a single name. These elements can be accessed using an index, making arrays a powerful tool for handling collections of data efficiently.

Declaration and Initialization:

In C++, declaring an array involves specifying the data type of its elements and the array’s name. Initialization can be done during declaration or later using assignment statements. Let’s take a look at the syntax:

// Declaration
int myArray[5];

// Initialization during declaration
int anotherArray[] = {1, 2, 3, 4, 5};

// Accessing elements
cout << anotherArray[2]; // Output: 3

Array Indexing:
Array indexing starts from 0, meaning the first element is accessed using index 0, the second with index 1, and so on. Be cautious not to access elements beyond the array’s bounds, as it can lead to undefined behavior.

Manipulating Arrays:
Iterating Through an Array:
Looping through an array is a common operation. You can use a for loop to access each element:

for (int i = 0; i < 5; ++i) {
    cout << myArray[i] << " ";
}

Array Size:
Determining the size of an array is crucial for avoiding index out-of-bounds errors. You can use the sizeof operator or calculate the size using the number of elements and data type size:

int size = sizeof(anotherArray) / sizeof(anotherArray[0]);

Example 1:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }
    
    for (int i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }

    return 0;
}

This program takes input for an array of integers and then prints the entered values.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int arr[7];
    for (int i = 0; i < 7; i++)
    {
        cin >> arr[i];
    }

    for (int i = 0; i < 7; i++)
    {
        cout << "index" << i << " = " << arr[i];
        cout << endl;
    }
    cout << endl;

    return 0;
}

This program is a simple console application that takes input for an array of 7 integers from the user and then displays each element along with its index.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    char g[5];
    cin.get(g, 5);
    cout << g << endl;

    return 0;
}

This program demonstrates reading a character array from user input using cin.get().

char g[5];
This line declares a character array named g that can hold 5 characters.

cin.get(g, 5);
This line uses cin.get() to read up to 4 characters (since the array size is 5, one space is reserved for the null terminator \0) from the user and stores them in the character array g. It stops reading when it encounters a newline character, the end of the stream, or when the specified number of characters have been read.

In summary, this program prompts the user to enter up to 4 characters (excluding the null terminator) and then prints the entered characters using cout.

The null terminator

Often represented by the character \0 (backslash followed by zero), is a special character used in C and C++ to denote the end of a string. It is essential for string manipulation functions to determine where a string ends in memory.

In memory, a string is represented as an array of characters. The null terminator is placed at the end of this array to indicate the boundary of the string. When a program processes a string, it can keep reading characters until it encounters the null terminator, signifying the end of the string data.

For example:

const char myString[] = "Hello";

In memory, this would be stored as follows:

H   e   l   l   o   \0

Here, the null terminator \0 follows the characters of the string, indicating the end of the string. Functions that operate on strings, like those in the C Standard Library or C++ Standard Library, use the null terminator to determine the length of the string and to recognize the end of the string when performing operations.

Example 4:

#include <iostream>
using namespace std;

int main()
{
    char g1[10];
    char g2[10];
    cin.getline(g1, 10);
    cin.getline(g2, 10);
    
    cout << g1 << endl;
    cout << g2 << endl;

    return 0;
}

This program demonstrates the use of the cin.getline() function to read input lines into character arrays and then prints them.

char g1[10];
char g2[10];

These lines declare two character arrays, g1 and g2, each capable of holding up to 9 characters plus the null terminator \0.

cin.getline(g1, 10);
cin.getline(g2, 10);

These lines use cin.getline() to read lines of input from the user into the character arrays g1 and g2. The function takes two arguments: the array to store the input (g1 or g2) and the maximum number of characters to read (9 in this case, leaving one space for the null terminator). The getline function reads characters until it encounters a newline character (‘\n’) or reaches the specified limit.

In summary, this program allows the user to input two lines of text, each up to 9 characters long, and then prints the entered lines. The use of cin.getline() ensures that the input is read as a line, and the program avoids potential issues with the input buffer.

Example 5:

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    char a1[] = "A";
    char a2[] = "B";
    cout << strcmp(a1, a2);

    return 0;
}

This C++ program compares two strings using the strcmp function from the C Standard Library.

This code includes the necessary header files for input/output operations (iostream) and string-related functions (cstring). The cstring header is included for the strcmp function.

char a1[] = "A";
char a2[] = "B";

These lines declare and initialize two character arrays, a1 and a2. Each array contains a single character and is automatically null-terminated by the compiler. Remember that a string in C/C++ is essentially an array of characters terminated by the null character (‘\0’).

cout << strcmp(a1, a2);

This line uses the strcmp function to compare the strings stored in a1 and a2. The result is printed to the console. The strcmp function returns an integer value:

  • If the strings are equal, it returns 0.
  • If a1 is lexicographically less than a2, it returns a negative value.
  • If a1 is lexicographically greater than a2, it returns a positive value.

The result of the comparison is printed to the console. This will be either 0 if the strings are equal, a negative value if a1 is less than a2, or a positive value if a1 is greater than a2.

 

Multi-dimensional Arrays:
C++ supports multi-dimensional arrays, which can be thought of as arrays of arrays. A 2D array, for example, can be declared and accessed like this:

int matrix[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

Additional Tips:
Passing Arrays to Functions:
When passing an array to a function, you need to use pointers. Here’s a quick example:

void printArray(int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        cout << arr[i] << " ";
    }
}

Standard Template Library (STL) Arrays:
For more advanced functionalities, consider using the array class from the C++ Standard Template Library (STL). It provides additional features and safety checks.

#include <array>

std::array<int, 5> stlArray = {1, 2, 3, 4, 5};

Example 6:

#include <iostream>
#include <cstring>
using namespace std;

void search(int arr[], int s, int k)
{
    bool g = false;
    for (size_t i = 0; i < s; i++)
    {
        if (arr[i] == k)
            g = true;
    }
    if (g)
        cout << "Found\n";
    else
        cout << "Not Found\n";
}

int main()
{
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    search(arr, 7, 55);
    

    return 0;
}

This program defines a function called search that searches for a specific value in an integer array. The main function then calls this search function to check if a particular value is present in the given array.

The function called search takes three parameters: arr (an integer array), s (the size of the array), and k (the value to search for).
It initializes a boolean variable g to false, which will be used to track whether the value k is found in the array.
The function then iterates through the array using a for loop. If the current element is equal to the target value k, it sets g to true.
After the loop, it checks the value of g and prints either “Found” or “Not Found” based on whether the target value was found in the array.

The main function initializes an integer array arr with values.
It then calls the search function, passing the array arr, the size of the array (7), and the value to search for (55).

Depending on whether the value 55 is found in the array, the program will output either “Found” or “Not Found.”

Example 7:

#include <iostream>
using namespace std;

void sort(int arr[], int s)
{
    int t;
    for (size_t i = 0; i < s - 1; i++)
    {
        for (size_t j = 0; j < s - 1; j++)
        {
            if (arr[j] > arr[j+1])
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
}

int main()
{
    int t;
    int arr[] = {22, 55, 88, 99, 1, 0, 7};
    sort(arr, 7);
    for (size_t i = 0; i < 7; i++)
    {
        cout << arr[i] << " ";
    }
    return 0;
}

This program implements a simple sorting algorithm known as the Bubble Sort.

The sort function implements the Bubble Sort algorithm for sorting an array of integers.
It takes two parameters: arr (the integer array to be sorted) and s (the size of the array).
The function uses nested for loops to iterate through the array. The inner loop compares adjacent elements and swaps them if they are in the wrong order, pushing the larger element towards the end of the array.
The process repeats until the entire array is sorted in ascending order.

The main function initializes an integer array arr with values.
It then calls the sort function, passing the array arr and its size (7), which sorts the array using the Bubble Sort algorithm.
Finally, the sorted array is printed using a for loop.

The program will output the sorted array: 0 1 7 22 55 88 99

Conclusion:
Mastering arrays in C++ is a crucial step in becoming a proficient programmer. They serve as the building blocks for more complex data structures and algorithms. If you’ve found this review helpful, don’t forget to check out our video tutorials on [Adel Nasim] for hands-on examples and practical insights.

Classes

What is a Class?

In C++, a class is a user-defined data type that encapsulates data and the functions that operate on that data. It serves as a blueprint for creating objects, which are instances of the class. Imagine a class as a template that defines the structure and behavior of objects.

To declare a class in C++, you use the class keyword.

Once a class is defined, you can create objects of that class. Objects are instances of the class, each with its own set of data.

In C++, classes support access modifiers like public, private, and protected. These modifiers control the visibility and accessibility of class members.

Example 1:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

class car{
    private: 
        char name[15];
        char color[10];
        int maxSpeed;
        int model;
    public:
        void setName(char n[])
        {
            strcpy_s(name, n);
        }
        void setColor(char n[])
        {
            strcpy_s(color, n);
        }
        void setMaxSpeed(int m)
        {
            maxSpeed = m;
        }
        void setModel(int m)
        {
            model = m;
        }
        char* getName()
        {
            return name;
        }
        char* getColor()
        {
            return color;
        }
        int getMaxSpeed()
        {
            return maxSpeed;
        }
        int getModel()
        {
            return model;
        }
        void print()
        {
            cout << "name = " << name << "\n"
            << "color = " << color << "\n"
            << "maxspeed = " << maxSpeed << "\n"
            << "model = " << model << "\n";
        }
};
int main()
{
    car x;
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);
    x.print();
    return 0;
}

This C++ code defines a simple class named car that represents information about a car, such as its name, color, maximum speed, and model. The program creates an instance of this class, sets its attributes, and prints the details using member functions. Let’s break down the code step by step:

  • Class Definition: car
class car {
private: 
    char name[15];
    char color[10];
    int maxSpeed;
    int model;
public:
    // Member functions for setting attributes
    void setName(char n[]) { strcpy_s(name, n); }
    void setColor(char n[]) { strcpy_s(color, n); }
    void setMaxSpeed(int m) { maxSpeed = m; }
    void setModel(int m) { model = m; }

    // Member functions for retrieving attributes
    char* getName() { return name; }
    char* getColor() { return color; }
    int getMaxSpeed() { return maxSpeed; }
    int getModel() { return model; }

    // Member function to print details
    void print() {
        cout << "name = " << name << "\n"
             << "color = " << color << "\n"
             << "maxspeed = " << maxSpeed << "\n"
             << "model = " << model << "\n";
    }
};

– Private Members: The class has private member variables (name, color, maxSpeed, and model), which can only be accessed within the class.

– Public Members: The class provides public member functions (setName, setColor, setMaxSpeed, etc.) to set and retrieve the values of these private variables.

  • main Function:
int main() {
    car x;

    // Setting attributes of the car
    x.setName("kia");
    x.setColor("red");
    x.setMaxSpeed(300);
    x.setModel(2017);

    // Printing the details using the print() member function
    x.print();

    return 0;
}

– Object Creation: An object x of type car is created.

– Setting Attributes: The attributes of the car (name, color, maxSpeed, and model) are set using the member functions (setName, setColor, setMaxSpeed, and setModel).

– Printing Details: The details of the car are printed using the print member function, which displays the values of the car’s attributes.

The output of this program would be:

name = kia
color = red
maxspeed = 300
model = 2017

This demonstrates a simple usage of a class in C++, encapsulating data and behavior related to a car. The class provides methods to set and retrieve attributes, promoting encapsulation and data hiding. This is a fundamental concept in object-oriented programming.

Example 2:

#include <iostream>
using namespace std;

class triangle{
    private: 
        float base;
        float height;
    public:
        void setBase_height(float b, float h)
        {
            base = b;
            height = h;
        }
        float area()
        {
            return 0.5 * base * height;
        }
        void print()
        {
            cout << "base = " << base << endl
            << "height = " << height << endl
            << "area = " << area() << endl;
        }
};
int main()
{
    triangle ob;
    ob.setBase_height(5, 10);
    ob.print();
    return 0;
}

This code defines a class named triangle that represents a triangle. The class has private member variables for the base and height of the triangle, and it provides member functions for setting these values, calculating the area, and printing the details of the triangle. Let’s break down the code step by step:

  • Class Definition: triangle
class triangle {
private: 
    float base;
    float height;

public:
    // Member function to set base and height
    void setBase_height(float b, float h) {
        base = b;
        height = h;
    }

    // Member function to calculate the area of the triangle
    float area() {
        return 0.5 * base * height;
    }

    // Member function to print details of the triangle
    void print() {
        cout << "base = " << base << endl
             << "height = " << height << endl
             << "area = " << area() << endl;
    }
};

– Private Members: The class has private member variables base and height, which can only be accessed within the class.

– Public Members: The class provides public member functions (setBase_height, area, and print) to set the base and height, calculate the area, and print the details of the triangle.

  • main Function:
int main() {
    triangle ob;

    // Setting base and height of the triangle
    ob.setBase_height(5, 10);

    // Printing the details of the triangle
    ob.print();

    return 0;
}

– Object Creation: An object ob of type triangle is created.

– Setting Base and Height: The setBase_height member function is called to set the base to 5 and height to 10 for the triangle.

– Printing Details: The print member function is called to print the details of the triangle, including the base, height, and calculated area.

The output of this program would be:

base = 5
height = 10
area = 25

This demonstrates a basic usage of a class in C++ to represent and manipulate data related to a triangle. The class encapsulates the data and behavior related to the triangle, promoting encapsulation and making the code more organized and reusable. The program calculates and displays the area of the triangle using the provided member functions.

Constructors

What is a Constructor?
In C++, a constructor is a special member function within a class that is automatically invoked when an object of that class is created. Its primary purpose is to initialize the object’s data members or perform any necessary setup for the object. Constructors ensure that the object starts with a valid state.

  1. Constructor Name:
    Constructors have the same name as the class they belong to.
  2. No Return Value:
    Constructors do not return any value, not even void.
  3. Object Initialization:
    Constructors are used to initialize and set up a new object when it is created.

Types of Constructors:

  1. Default/ Empty Constructor:
    Automatically generated by the compiler if no constructor is explicitly defined.
    Initializes object members with default values.
    Syntax: ClassName() { /* Initialization code */ }
    Example 1:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height =h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob;
        ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }

    An empty constructor is defined (Triangle()). It is automatically called when an object is created and prints “first constructor.”

  2. Parameterized Constructor:
    Accepts parameters during object creation to customize the initial state.
    Provides flexibility for objects to start with different values.
    Syntax: ClassName(type param1, type param2, …) { /* Initialization code */ }
    Example 2:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    class Triangle
    {
        private:
            int base;
            int height;
        public:
            //empty constructor, no arguments are required
            Triangle()
            {
                cout << "first constructor\n";
                base = 0;
                height = 0;
            }
            //parameterized constructor
            Triangle(int b, int h)
            {
                base = b;
                height = h;
                cout << "parameterized constructor\n";
            }
            void setBase_Height(int b, int h)
            {
                base = b;
                height = h;
            }
            float area()
            {
                return 0.5*base*height;
            }
            void print()
            {
                cout << "base = " << base << endl
                     << "height = " << height << endl
                     << "area = " << area() << endl;
            }
    };
    int main()
    {
        Triangle ob(5, 10);
        //ob.setBase_Height(10, 5);
        ob.print();
    
        return 0;
    }
    

    Parameterized Constructor:

    Accepts parameters (int b and int h) for custom initialization.
    Prints “parameterized constructor” when called.
    The parameterized constructor is employed during object creation, providing initial values for the base and height members.

Example 3:

#include <iostream>
#include <cstdlib>
using namespace std;
class student {
    private:
        char name[20];
        int id;
    public:
        student()
        {
            strcpy_s(name, "no name");
            id = 0;
        }
        student(char n[], int i)
        {
            cout << "parameterized constructor\n";
            strcpy_s(name, n);
            id = i;
        }
        student(char n[])
        {
            strcpy_s(name, n);
        }
        void print()
        {
            cout << "name = " << name << endl;
            cout << "id = " << id << endl;
        }
};
int main()
{
    student ob("Mohammed", 1450902032);
    ob.print();

    return 0;
}

This code defines a class student representing a student with private member variables name and id. The class includes three constructors: an empty constructor, a parameterized constructor with both name and id, and a parameterized constructor with only the name. Let’s break down the code step by step:

– Class Definition: student

class student {
private:
    char name[20];
    int id;

public:
    // Empty Constructor
    student() {
        strcpy_s(name, "no name");
        id = 0;
    }

    // Parameterized Constructor (with name and id)
    student(char n[], int i) {
        cout << "parameterized constructor\n";
        strcpy_s(name, n);
        id = i;
    }

    // Parameterized Constructor (with name only)
    student(char n[]) {
        strcpy_s(name, n);
    }

    // Member Function to print student details
    void print() {
        cout << "name = " << name << endl;
        cout << "id = " << id << endl;
    }
};
  • Empty Constructor:
    Initializes name to “no name” and id to 0.
  • Parameterized Constructor (with name and id):
    Accepts parameters (char n[] and int i).
    Prints “parameterized constructor” when called.
    Sets name and id based on the provided values.
  • Parameterized Constructor (with name only):
    Accepts a parameter (char n[]).
    Initializes only the name attribute.
  • Member Function:
    print: Displays the student’s name and id.

– main Function:

int main() {
    // Object of class student created using the parameterized constructor with name and id
    student ob("Mohammed", 1450902032);

    // Printing the details of the student
    ob.print();

    return 0;
}
  • Object Creation:
    An object ob of type student is created using the parameterized constructor with both name and id.
  • Printing Details:
    The print member function is called to display the details of the student, including the name and id.

The output of this program would be:

parameterized constructor
name = Mohammed
id = 1450902032

This code illustrates the use of multiple constructors in a C++ class. Depending on the provided arguments during object creation, different constructors can be called to initialize the object accordingly.

3. Copy Constructor:

Example 4:

#include <iostream>
using namespace std;
class Copy {
    private:
        int a1, a2, a3, a4, a5, a6, a7, a8;
    public:
        Copy(int aa1, int aa2, int aa3, int aa4,
            int aa5, int aa6, int aa7, int aa8)
        {
            a1 = aa1;
            a2 = aa2;
            a3 = aa3;
            a4 = aa4;
            a5 = aa5;
            a6 = aa6;
            a7 = aa7;
            a8 = aa8;
        }
        Copy(const Copy &a)
        {
            a1 = a.a1;
            a2 = a.a2;
            a3 = a.a3;
            a4 = a.a4;
            a5 = a.a5;
            a6 = a.a6;
            a7 = a.a7;
            a8 = a.a8;
        }
        void print()
        {
            cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
                 << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
        }
};
int main()
{
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    g.print();
    Copy h(g);
    h.print();

    return 0;
}

This code defines a class Copy with two constructors – one for initializing an object with specific values and another for performing a deep copy of an existing object. Let’s break down the code:

– Class Definition: Copy

class Copy {
private:
    int a1, a2, a3, a4, a5, a6, a7, a8;

public:
    // Parameterized Constructor for Initialization
    Copy(int aa1, int aa2, int aa3, int aa4,
         int aa5, int aa6, int aa7, int aa8) {
        a1 = aa1;
        a2 = aa2;
        a3 = aa3;
        a4 = aa4;
        a5 = aa5;
        a6 = aa6;
        a7 = aa7;
        a8 = aa8;
    }

    // Copy Constructor for Deep Copy
    Copy(const Copy &a) {
        a1 = a.a1;
        a2 = a.a2;
        a3 = a.a3;
        a4 = a.a4;
        a5 = a.a5;
        a6 = a.a6;
        a7 = a.a7;
        a8 = a.a8;
    }

    // Member Function to Print Object Details
    void print() {
        cout << a1 << " " << a2 << " " << a3 << " " << a4 << " "
             << a5 << " " << a6 << " " << a7 << " " << a8 << " " << endl;
    }
};
  • Parameterized Constructor:
    Initializes the object with specific values provided as arguments.
  • Copy Constructor:
    Performs a deep copy of an existing object (Copy &a).
    Copies each member variable of the source object to the new object.
  • Print Function:
    Displays the values of the object’s member variables.

– main Function:

int main() {
    // Creating an object 'g' and initializing it with specific values
    Copy g(1, 2, 3, 4, 5, 6, 7, 8);
    
    // Printing the details of object 'g'
    g.print();

    // Creating another object 'h' and initializing it by performing a deep copy of 'g'
    Copy h(g);

    // Printing the details of object 'h'
    h.print();

    return 0;
}
  • Object Creation (g):
    An object g of type Copy is created and initialized with specific values.
  • Printing Details (g):
    The print member function is called to display the details of object g.
  • Object Creation (h):
    Another object h is created and initialized by performing a deep copy of object g using the copy constructor.
  • Printing Details (h):
    The print member function is called to display the details of object h

The output of this program would be:

1 2 3 4 5 6 7 8 
1 2 3 4 5 6 7 8 

This code illustrates the usage of a copy constructor to create a new object with the same values as an existing object, ensuring a deep copy of the data.

Destructor

What is a Destructor?

In C++, a destructor is a special member function that is automatically called when an object goes out of scope or is explicitly deleted. Its primary purpose is to clean up resources or perform actions before the object’s memory is deallocated.

Destructor Charachteristics:

  1. Name and Syntax:
    Name: Destructors have the same name as the class, preceded by a tilde (~).
    Syntax: ~ClassName()
  2. Automatic Invocation:
    Destructors are automatically invoked when an object goes out of scope or is explicitly deleted.
    They handle the cleanup and deallocation of resources held by the object.
  3. No Return Type or Parameters:
    Destructors don’t have a return type, not even void.
    They do not accept any parameters.
  4. Single Destructor per Class:
    Each class can have only one destructor.
    It’s responsible for cleaning up resources allocated during the object’s lifetime.
  5. Manual Deletion:
    For objects created dynamically using new, the destructor is called explicitly using delete.
    This is essential for releasing memory allocated on the heap.
  6. Resource Cleanup:
    Destructors are often used to release resources such as dynamic memory, file handles, database connections, etc.
    Ensures proper cleanup before the object is destroyed.

Why Use Destructors?

Destructors are essential for proper resource management and maintaining the integrity of your program. They are particularly useful when dealing with dynamic memory allocation, file handling, or any situation where cleanup is necessary.

Syntax of a Destructor:

The syntax for a destructor is straightforward. It has the same name as the class preceded by a tilde (~). Here’s an example:

class MyClass {
public:
    // Constructor
    MyClass() {
        // Constructor code
    }

    // Destructor
    ~MyClass() {
        // Destructor code
    }
};

Example 1:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(int a, int b)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}

This code defines a class Rectangle representing a rectangle with private member variables W (width) and H (height). The class includes a constructor for creating a rectangle and a destructor for cleaning up resources when the rectangle is deleted. Let’s break down the code:

– Class Definition: Rectangle

class Rectangle {
private:
    int W, H;

public:
    // Constructor
    Rectangle(int a, int b) {
        W = a;
        H = b;
        cout << "A rectangle has been created\n";
    }

    // Destructor
    ~Rectangle() {
        cout << W << " " << H << " A rectangle has been deleted\n";
    }
};
  • Constructor:
    Initializes the W (width) and H (height) member variables with the values passed as arguments.
    Prints a message indicating that a rectangle has been created.
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

– main Function:

int main() {
    // Creating two objects of class Rectangle
    Rectangle R1(3, 4), R2(5, 6);

    return 0;
}
  • Object Creation:
    Two objects, R1 and R2, of type Rectangle are created in the main function.
  • Constructor Execution:
    The constructor of the Rectangle class is executed for each object, initializing their width and height.
    Messages are printed indicating that rectangles have been created.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for R1 and R2 are automatically called.
    Messages are printed indicating that rectangles have been deleted, along with their dimensions.

The output of this program would be:

A rectangle has been created
A rectangle has been created
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

This output demonstrates the automatic invocation of the constructor when objects are created and the destructor when objects go out of scope (at the end of the program in this case). The destructor prints messages indicating the deletion of rectangles along with their dimensions.

Example 2:

#include <iostream>
using namespace std;
class Rectangle {
    private:
        int W, H;
    public:
        Rectangle(): W(0), H(0)
        {
            cout << "W = " << W << " H = " << H << endl;
        }
        Rectangle(int a, int b): W(0), H(0)
        {
            W = a;
            H = b;
            cout << "A rectangle has been created\n";
            Rectangle ob;
        }
        ~Rectangle()
        {
            cout << W << " " << H << " A rectangle has been deleted\n";
        }
};
int main()
{
    Rectangle R1(3, 4), R2(5, 6);
    Rectangle R3;

    return 0;
}
  • Default Constructor:
    Initializes W and H to 0.
    Prints the initial values of W and H when an object is created with this constructor.
  • Parameterized Constructor:
    Accepts parameters a and b to set the dimensions of the rectangle.
    Initializes W and H to 0 before assigning the provided values.
    Prints a message indicating that a rectangle has been created.
    Creates another object ob inside the constructor (not recommended in general practice).
  • Destructor:
    Prints a message with the dimensions of the rectangle when it is deleted.

The output of this program would be:

A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
A rectangle has been created
W = 0 H = 0
0 0 A rectangle has been deleted
W = 0 H = 0
0 0 A rectangle has been deleted
5 6 A rectangle has been deleted
3 4 A rectangle has been deleted

Example 3:

#include <iostream>
using namespace std;
class phone {
    private:
        char name[10];
        char model[10];
        int price;
    public:
        phone() {}
        phone(char n[], char m[], int p)
        {
            strcpy(name, n);
            strcpy(model, m);
            price = p;
        }
        void print();
        ~phone();
};
phone::~phone()
{
    cout << "object destructed\n"
}
void phone::print()
{
    cout << "Name = " << name << endl;
    cout << "Model = " << model << endl;
    cout << "Price = " << price << endl;
}
int main()
{
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();
    return 0;
}

This code defines a class phone representing a phone with private member variables name, model, and price. The class includes a default constructor, a parameterized constructor, a member function (print), and a destructor. Let’s break down the code:

– Class Definition: phone

class phone {
private:
    char name[10];
    char model[10];
    int price;

public:
    // Default Constructor
    phone() {}

    // Parameterized Constructor
    phone(char n[], char m[], int p) {
        strcpy(name, n);
        strcpy(model, m);
        price = p;
    }

    // Member Function to Print Phone Details
    void print();

    // Destructor
    ~phone();
};
  • Default Constructor:
    An empty default constructor is provided.
  • Parameterized Constructor:
    Accepts parameters n (name), m (model), and p (price) to initialize the object’s member variables.
  • Member Function (print):
    Displays the details of the phone, including its name, model, and price.
  • Destructor:
    Outputs a message when an object of the class is destructed.

– Destructor Implementation:

phone::~phone() {
    cout << "object destructed\n";
}

The destructor is defined outside the class and prints a message when an object of the class is destructed.

– main Function:

int main() {
    phone ob1, ob2("HUAWI", "MATE 9", 400);
    ob2.print();

    return 0;
}
  • Object Creation:
    Two objects, ob1 and ob2, of type phone are created.
    ob2 is initialized using the parameterized constructor.
  • Printing Details:
    The print member function is called for ob2 to display its details.
  • Object Destruction:
    When the program exits, or when the main function scope is left, the destructors for ob1 and ob2 are automatically called.
    A message is printed indicating that an object has been destructed.

The output of this program would be:

Name = HUAWI
Model = MATE 9
Price = 400
object destructed

This output demonstrates the creation, printing, and destruction of phone objects, including the use of the parameterized constructor and the destructor.

Example 4:

#include <iostream>
#include <cstring>
using namespace std;
class Student {
    private:
        char name[20];
        int ID;
    public:
        Student()
        {
            cout << "Object created\n";
        }
        ~Student()
        {
            cout << "Object destructed\n";
        }
        void Set_Name_ID(char n[], int id)
        {
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
}; //end of class definition
void F(Student S)
{
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
int main()
{
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Funcrion\n";
    St1.print();
    return 0;
}

This code defines a class Student representing a student with private member variables name and ID. The class includes a default constructor, a destructor, a member function to set the name and ID, and another member function to print the student’s details. Additionally, there is a function F that takes a Student object as a parameter and demonstrates object creation, assignment, modification, and destruction within a function. Let’s break down the code:

– Class Definition: Student

class Student {
private:
    char name[20];
    int ID;

public:
    // Default Constructor
    Student() {
        cout << "Object created\n";
    }

    // Destructor
    ~Student() {
        cout << "Object destructed\n";
    }

    // Member Function to Set Name and ID
    void Set_Name_ID(char n[], int id) {
        strcpy(name, n);
        ID = id;
    }

    // Member Function to Print Student Details
    void print(void) {
        cout << name << "\t" << ID << endl;
    }
};
  • Default Constructor:
    Prints a message indicating that an object has been created.
  • Destructor:
    Prints a message indicating that an object has been destructed.
  • Set_Name_ID Function:
    Accepts parameters n (name) and id (ID) to set the member variables.
  • print Function:
    Prints the name and ID of the student.

– Function F:

void F(Student S) {
    Student S1;
    S1 = S;
    S.Set_Name_ID("Sami", 12345);
    S.print();
    S1.print();
}
  • Creates a Student object S1 within the function.
  • Copies the content of the parameter S into S1.
  • Modifies the content of S using the Set_Name_ID function.
  • Prints the details of both S and S1.

– main Function:

int main() {
    Student St1, St2;
    St1.Set_Name_ID("Ahmad", 11111);
    St2.Set_Name_ID("Ali", 22222);
    cout << "Going to Function\n";
    F(St1);
    cout << "Back from Function\n";
    St1.print();
    return 0;
}
  • Object Creation and Modification:
    Creates two Student objects, St1 and St2.
    Sets their names and IDs using the Set_Name_ID function.
  • Function Call:
    Calls the function F passing St1 as a parameter.
  • Object Destruction:
    Prints messages indicating the destruction of objects when they go out of scope (end of the function or program).

The output of this program would be:

Object created
Object created
Going to Function
Object created
Sami    12345
Ahmad   11111
Object destructed
Object destructed
Back from Funcrion
Ahmad   11111
Object destructed
Object destructed

This output demonstrates the creation, modification, and destruction of Student objects, including the behavior of the default constructor and destructor. The F function illustrates object copying and modification within a function.

Structure

Structures in C++ provide a powerful way to organize and store related data under a single name. They are a fundamental concept in Object-Oriented Programming (OOP) that allows you to create custom data types to suit your program’s needs. In this guide, we’ll delve into the basics of structures in C++.

What is a Structure?

A structure is a user-defined data type in C++ that enables you to group together different data types under a single name. This makes it easier to manage and organize related information. Unlike primitive data types, structures can hold a collection of variables with various data types.

Defining a Structure:

To create a structure, you use the struct keyword, followed by the structure’s name and a block of variables inside curly braces. Here’s a simple example:

// Define a structure named 'Person'
struct Person {
    char name[50];
    int age;
    float height;
};

In this example, we’ve created a structure named Person with three members: a character array for the name, an integer for age, and a float for height.

Accessing Structure Members:

You can access the members of a structure using the dot (.) operator.

Example 1:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
};

int main()
{
    car g;
    g.name = "Kia";
    g.color = "red";
    cout << g.name << endl; //Kia
    cout << g.color << endl;  //red

    return 0;
}

This code defines a simple program that utilizes a structure named car. The structure car has four members: name (string), color (string), maxspeed (integer), and model (integer). The program then declares a variable g of type car and assigns values to its name and color members. Finally, it prints the values of name and color to the console.

Initializing Structure Variables:

You can initialize structure variables at the time of declaration, similar to how you initialize primitive variables:

// Initialize structure variables
Person person3 = {"Alice", 30, 5.5};

Example 2:

#include <iostream>
using namespace std;

struct car 
{
    string name;
    string color;
    int maxspeed;
    int model;
}g, k;

int main()
{
    k = {"aa", "black", 300, 97};
    g = {"kia", "red", 250, 96};
    cout << g.maxspeed << endl;

    return 0;
}

This code defines a structure named car with four members (name, color, maxspeed, and model). Additionally, it declares two structure variables, g and k, of type car. In the main function, it assigns values to these structure variables using an initialization syntax and then prints the value of the maxspeed member of the g structure variable. Here’s a detailed explanation:

– Structure Definition and Variable Declaration:

struct car {
    string name;
    string color;
    int maxspeed;
    int model;
} g, k;  // Declaration of structure variables g and k of type car

Defines a structure named car and declares two structure variables g and k of type car.

– Main Function:

int main() {
    // Initialization of structure variable k
    k = {"aa", "black", 300, 97};

    // Initialization of structure variable g
    g = {"kia", "red", 250, 96};

    // Print the value of the maxspeed member of the g structure variable
    cout << g.maxspeed << endl;

    return 0;
}

Execution Flow:

  1. Initialization of Variables:
    k = {“aa”, “black”, 300, 97}; initializes the members of structure variable k with the provided values.
    g = {“kia”, “red”, 250, 96}; initializes the members of structure variable g with the provided values.
  2. Print to Console:
    cout << g.maxspeed << endl; prints the value of the maxspeed member of the g structure variable to the console, followed by a newline.
  3. Return Statement:
    return 0; indicates that the program has executed successfully.

The output of this program would be:

250

Functions and Structures:

Structures can be passed as arguments to functions, allowing you to create more modular and organized code.

Example 3:

#include <iostream>
#include <string>
using namespace std;

struct Distance
{
    int feet;
    float inches;
};
Distance add_distance(Distance d1, Distance d2)
{
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

int main()
{
    Distance x, y, z;
    cout << "Enter feet value \n";
    cin >> x.feet >> y.feet;
    cout << "Enter inches value \n";
    cin >> x.inches >> y.inches;
    z = add_distance(x, y);
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

This code demonstrates the use of structures to represent distances in feet and inches. It defines a structure Distance with two members: feet (integer) and inches (float). The program then includes a function add_distance to add two distance structures, and the main function takes user input for two distances, adds them using the add_distance function, and prints the result. Here’s a step-by-step explanation:

– Structure Definition:

struct Distance {
    int feet;
    float inches;
};

Defines a structure named Distance with two members: feet (integer) and inches (float).

– Function to Add Distances:

Distance add_distance(Distance d1, Distance d2) {
    Distance result;
    result.feet = d1.feet + d2.feet;
    result.inches = d1.inches + d2.inches;
    return result;
}

Defines a function add_distance that takes two Distance structures as parameters, adds their corresponding feet and inches members, and returns a new Distance structure representing the sum.

– Main Function:

int main() {
    Distance x, y, z;

    // User input for the first distance (x)
    cout << "Enter feet value \n";
    cin >> x.feet;
    cout << "Enter inches value \n";
    cin >> x.inches;

    // User input for the second distance (y)
    cout << "Enter feet value \n";
    cin >> y.feet;
    cout << "Enter inches value \n";
    cin >> y.inches;

    // Add the two distances using the add_distance function
    z = add_distance(x, y);

    // Print the result
    cout << "z.feet = " << z.feet << " z.inches = " << z.inches << endl;

    return 0;
}

Execution Flow:

  1. User Input:
    The user is prompted to enter the feet and inches values for two distances (x and y).
  2. Function Call:
    The add_distance function is called with the x and y structures as arguments, and the result is stored in the z structure.
  3. Print to Console:
    The program prints the result, displaying the summed feet and inches of the distances.
  4. Return Statement:
    return 0; indicates that the program has executed successfully.

– Sample Execution:
If the user enters:

Enter feet value
3
Enter inches value
6.5
Enter feet value
2
Enter inches value
3.2

The program would output:

z.feet = 5 z.inches = 9.7

Example 4:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;

struct exam
{
    float first;
    float second;
    float final;
};
class subject
{
        char name[10];
        exam Exam;
    public:
        subject()
        {
            strcpy(name, "no name");
            Exam = {0, 0, 0};
        }
        subject(char n[], float fa, float s, float fi)
        {
            strcpy(name, n);
            Exam = {fa, s, fi};
        }
        float total()
        {
            return Exam.first + Exam.second + Exam.final;
        }
        void print()
        {
            cout << "The subject = " << name << endl
                 << "First Exam = " << Exam.first << endl
                 << "Second Exam = " << Exam.second << endl
                 << "Final Exam = " << Exam.final << endl
                 << "The Total is = " << total() << endl;
        }
};

int main()
{
    subject e("OOP", 25, 24, 49);
    e.print();
    return 0;
}

This code defines a program that uses a combination of structures and classes to model a subject with exam scores. Let’s break down the code step by step:

– Structure Definition:

struct exam {
    float first;
    float second;
    float final;
};

Defines a structure named exam with three members representing exam scores: first, second, and final.

– Class Definition:

class subject {
    char name[10];
    exam Exam;
public:
    // Default constructor
    subject() {
        strcpy(name, "no name");
        Exam = {0, 0, 0};
    }

    // Parameterized constructor
    subject(char n[], float fa, float s, float fi) {
        strcpy(name, n);
        Exam = {fa, s, fi};
    }

    // Member function to calculate the total exam score
    float total() {
        return Exam.first + Exam.second + Exam.final;
    }

    // Member function to print subject details
    void print() {
        cout << "The subject = " << name << endl
             << "First Exam = " << Exam.first << endl
             << "Second Exam = " << Exam.second << endl
             << "Final Exam = " << Exam.final << endl
             << "The Total is = " << total() << endl;
    }
};

Defines a class named subject with private members:

  • name: An array of characters representing the subject’s name.
  • Exam: An instance of the exam structure representing exam scores.

The class includes:

  • A default constructor (subject()) initializing name to “no name” and Exam to all zeros.
  • A parameterized constructor (subject(char n[], float fa, float s, float fi)) initializing name and Exam with provided values.
  • A total() member function calculating the total exam score.
  • A print() member function printing subject details.

– Main Function:

int main() {
    // Create an instance of the subject class
    subject e("OOP", 25, 24, 49);

    // Call the print() member function to display subject details
    e.print();

    return 0;
}

In the main function:

  • An instance e of the subject class is created using the parameterized constructor.
  • The print() member function is called on the e object, displaying the details of the subject and its exam scores.

– Sample Output:

The subject = OOP
First Exam = 25
Second Exam = 24
Final Exam = 49
The Total is = 98

This output represents the details of the “OOP” subject, including scores on the first, second, and final exams, as well as the total score.

 

New Delete

In object-oriented programming (OOP) with C++, pointers play a crucial role in managing memory and accessing objects dynamically. Here’s a brief explanation of pointers in the context of OOP in C++:

Definition:

A pointer is a variable that holds the memory address of another variable. In C++, pointers can be used to store addresses of objects created dynamically on the heap.

Example 1:

int main()
{
    int var1 = 11;
    int var2 = 22;
    cout << &var1 << endl;
    cout << &var2 << endl;
    
    int *ptr;
    ptr = &var2;
    *ptr = 5000;
    cout << *ptr << endl;
    cout << var2 << endl;
}

This code demonstrates the use of pointers to manipulate variables and access their memory addresses.

  1. Variable Declaration and Initialization:
    int var1 = 11;
    int var2 = 22;
    

    Two integer variables, var1 and var2, are declared and initialized with values 11 and 22, respectively.

  2. Printing Memory Addresses:
    cout << &var1 << endl;
    cout << &var2 << endl;
    

    The memory addresses of var1 and var2 are printed using the address-of operator (&). This reveals the locations in memory where these variables are stored.

  3. Pointer Declaration and Assignment:
    int *ptr;
    ptr = &var2;
    

    A pointer variable ptr of type int is declared. The address of var2 is assigned to the pointer ptr.

  4. Using Pointer to Modify Variable:
    *ptr = 5000;
    

    The value pointed to by ptr is changed to 5000. Since ptr points to the address of var2, this also modifies the value of var2.

  5. Printing Pointer Value and Modified Variable:
    cout << *ptr << endl;
    cout << var2 << endl;
    

    The value pointed to by ptr (5000) and the modified value of var2 are printed. Both values should be the same, as the pointer was used to modify the content of var2.

The output of the code might look like this:

0x7fff5fbff628  // Memory address of var1
0x7fff5fbff624  // Memory address of var2
5000             // Value pointed to by ptr
5000             // Modified value of var2

The exact memory addresses and values may vary depending on the system and compiler.

Dynamic Memory Allocation:

OOP often involves the creation of objects using the new operator for dynamic memory allocation. Pointers are used to store the address of the dynamically allocated objects.

Deleting Dynamic Objects:

When dynamic objects are no longer needed, they should be explicitly deleted to avoid memory leaks. The delete operator is used.

Example 2:

#include <iostream>
using namespace std;

int main()
{
    int *p;
    p = new int;
    *p = 10;
    cout << p << endl;
    delete p;
}

This code demonstrates dynamic memory allocation and deallocation for an integer variable. Here’s an explanation of the code:

#include <iostream>
using namespace std;

int main()
{
    // Declare a pointer variable
    int *p;

    // Allocate memory for an integer on the heap
    p = new int;

    // Assign a value to the dynamically allocated integer
    *p = 10;

    // Print the address of the dynamically allocated memory
    cout << p << endl;

    // Deallocate the dynamically allocated memory
    delete p;

    return 0;
}

Explanation:

  1. Pointer Declaration:
    int *p;
    

    Declares a pointer variable p that will be used to store the address of a dynamically allocated integer.

  2. Dynamic Memory Allocation:
    p = new int;
    

    Allocates memory on the heap to store an integer and assigns the address of the allocated memory to the pointer p.

  3. Assigning a Value:
    *p = 10;
    

    Dereferences the pointer p and assigns the value 10 to the dynamically allocated integer.

  4. Printing the Address:
    cout << p << endl;
    

    Prints the address of the dynamically allocated memory. This address is on the heap and may vary each time the program runs.

  5. Memory Deallocation:
    delete p;
    

    Deallocates the memory previously allocated with new. This step is crucial to prevent memory leaks.

Example 3:

#include <iostream>
using namespace std;

int main()
{
    // Declare two pointer variables
    int *p1, *p2;

    // Allocate memory for the first integer on the heap
    p1 = new int;
    *p1 = 10;

    // Print the location of the pointer and the content of the allocated memory
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    // Allocate memory for the second integer on the heap
    p2 = new int;
    *p2 = 10;

    // Print the location of the second pointer and the content of the allocated memory
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;

    // Deallocate the dynamically allocated memory
    delete p1;
    delete p2;

    return 0;
}

This code demonstrates dynamic memory allocation for two integer variables using pointers. Here’s an explanation of the code:

  1. Pointer Declaration:
    int *p1, *p2;
    

    Declares two pointer variables, p1 and p2, which will be used to store the addresses of dynamically allocated integers.

  2. Dynamic Memory Allocation (p1):
    p1 = new int;
    *p1 = 10;
    

    Allocates memory on the heap for an integer using new, assigns the address to p1, and assigns the value 10 to the dynamically allocated integer.

  3. Printing Information (p1):
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    Prints the location of the pointer variable p1 and the content of the memory it points to.

  4. Dynamic Memory Allocation (p2):
    p2 = new int;
    *p2 = 10;
    

    Allocates memory on the heap for another integer using new, assigns the address to p2, and assigns the value 10 to the dynamically allocated integer.

  5. Printing Information (p2):
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;
    

    Prints the location of the pointer variable p2 and the content of the memory it points to.

  6. Memory Deallocation:
    delete p1;
    delete p2;
    

    Deallocates the dynamically allocated memory using delete to avoid memory leaks.

Example 4:

#include <iostream>
using namespace std;

class CRectangle 
{
        int *width, *height;
    public:
        CRectangle(int, int); //constructor
        ~CRectangle(); //destructor
        int area()
        {
            return (*width * *height);
        }
};
CRectangle::CRectangle(int a, int b)
{
    width = new int;
    height = new int;
    *width = a;
    *height = b;
}
CRectangle::~CRectangle()
{
    delete width;
    delete height;
}
int main()
{
    CRectangle rect(3, 4), rectb(5, 6);
    cout << "rect area: " << rect.area() << endl;
    cout << "rectb area: " << rectb.area() << endl;
    return 0;
}

This code defines a class CRectangle for rectangles using dynamic memory allocation for width and height. Here’s a breakdown of the code:

  1. Class Definition (CRectangle):
    The class CRectangle represents rectangles, with private members width and height stored as dynamic integer pointers.
  2. Constructor (CRectangle::CRectangle):
    The constructor allocates memory for width and height using new and initializes them with the provided values.
  3. Destructor (CRectangle::~CRectangle):
    The destructor deallocates the memory for width and height using delete.
  4. Member Function (area):
    The area function calculates and returns the area of the rectangle using the values stored in width and height.
  5. Main Function:
    Creates instances of CRectangle (rect and rectb) with dynamic memory allocation for width and height.
    Calls the area function to calculate and display the area of each rectangle.
    The destructors are automatically called when the instances (rect and rectb) go out of scope, freeing the dynamically allocated memory.

 

 

Array of object and Pointers to Objects

In the world of object-oriented programming (OOP) with C++, managing multiple objects efficiently is crucial. Two powerful concepts that help achieve this are Arrays of Objects and Pointers to Objects. This documentation will provide a clear understanding of both concepts and how they can be employed in C++.

Example 1:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};

    // Printing the memory address of the array (address of the first element)
    cout << arr << endl;

    // Printing the value at the first element of the array
    cout << *arr << endl;

    // Printing the memory address of the second element of the array
    cout << arr + 1 << endl;

    // Printing the memory address of the last element of the array
    cout << arr + 4 << endl;

    // Printing the value at the last element of the array
    cout << *(arr + 4) << endl;
    
    // Using a loop to print all elements of the array using pointer arithmetic
    for (size_t i = 0; i < 5; i++)
    {
        cout<< *(arr + i) << endl;
    }

    return 0;
}

This program demonstrates the use of pointers with arrays.

The output will display the memory addresses, values, and elements of the array based on the pointer arithmetic and loop iterations.

Example 2:

#include <iostream>
using namespace std;
int main()
{
    int arr[5] = {10, 50, 40, 77, 33};
    int *p;
    p = arr;
    for (size_t i = 0; i < 5; i++)
    {
        cout << *p << endl;
        p++;
    }

    return 0;
}

This C++ program demonstrates the use of a pointer to iterate through an array.

The output will display the values of each element in the array, printed one at a time, as the pointer p is incremented within the loop.

10
50
40
77
33

Note:

  • The pointer p is initially set to the address of the first element of the array.
  • Incrementing the pointer (p++) makes it point to the next element in the array.
  • This approach provides an alternative way to iterate through array elements using pointers.

Example 3:

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
class Student
{
        char name[20];
        int ID;
    public:
        Student() //empty constructor
        {
            cout << "empty\n";
            strcpy(name, "No name");
            ID = 0;
        }
        Student(char n[], int id) //constructor overloading
        {
            cout << "parameterize\n";
            strcpy(name, n);
            ID = id;
        }
        void print(void)
        {
            cout << name << "\t" << ID << endl;
        }
};
int main()
{
    Student S1("Ali", 123), S2("Ahmad", 456);
    Student arr[3];
    for (int i = 0; i < 3; i++)
        arr[i].print();
    return 0;
}

This program demonstrates the use of constructor overloading and default constructors in a class Student. Let’s break down the code:

  1. Class Student:
    Defines a class named Student with private data members name and ID.
    Contains two constructors: an empty constructor and a parameterized constructor.
    Provides a member function print() to display student details.
  2. Empty Constructor:
    Student()
    {
        cout << "empty\n";
        strcpy(name, "No name");
        ID = 0;
    }
    

    Initializes name with “No name” and ID with 0.
    Prints “empty” when an object is created using this constructor.

  3. Constructor Overloading:
    Student(char n[], int id)
    {
        cout << "parameterize\n";
        strcpy(name, n);
        ID = id;
    }
    

    Initializes name and ID with the provided arguments.
    Prints “parameterize” when an object is created using this constructor.

  4. print() Function:
    void print(void)
    {
        cout << name << "\t" << ID << endl;
    }
    
    

    Prints the student’s name and ID.

  5. Creating Objects:
    Objects S1 and S2 are created using the parameterized constructor, displaying “parameterize” for each object.
    An array arr of Student objects is created using the default constructor, displaying “empty” for each object.
  6. Printing Student Details:
    The print() function is called for each object in the array to display their details.

Output:
The output will display the constructor messages and the details of each student in the array.

 

 

 

Enumeration

Introduction

In C++, an enumeration, also known as enumerated type, is a user-defined data type that consists of a set of named integer constants. These constants are essentially representative names assigned to integer values.

Declaration:

  • The enum keyword is used to declare an enumeration.
  • You list the constant names separated by commas, optionally enclosed in curly braces.
  • By default, constants start with a value of 0 and increment by 1 for each subsequent one.
  • You can explicitly assign specific integer values to individual constants.

Example 1:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
enum days {sat = 1, sun, mon, tue, wed, thu, fri};
int main()
{
    string d[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
    days m[7] = {sat, sun, mon, tue, wed, thu, fri};
    for (size_t i = 0; i < 7; i++)
    {
        cout << m[i] << " - " << d[i] << endl;
    }
    return 0;
}

Enumeration days:

  • Declares an enumeration named days to represent the days of the week.
  • Assigns values to each day: sat = 1, sun, mon, etc. (subsequent days get implicit values incremented from the previous one).

String Array d:

  • Creates an array of strings named d with a size of 7, holding the full day names (“sat”, “sun”, …, “fri”).

Enumeration Array m:

  • Creates an array of enumeration values named m with a size of 7, containing the day enumerations (sat, sun, …, fri).

for Loop:

  • Iterates through the elements of both d and m using a single index i.
  • For each iteration:
    – Prints the current enumeration value from m[i] followed by a hyphen (“-“).
    – Prints the corresponding day name from d[i] on the same line.

Example 2:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
string da[7] = {"sat", "sun", "mon", "tue", "wed", "thu", "fri"};
enum Days {sat = 1, sun, mon, tue, wed, thu, fri};
class week {
        Days d[7];
    public:
        void setday(Days w[])
        {
            for (size_t i = 0; i < 7; i++)
                d[i] = w[i];
        }
        void p()
        {
            for (size_t i = 0; i < 7; i++)
                cout << "The number of day " <<  da[i] << " = " << d[i] << endl;
        }
};
int main()
{
    Days d[7] = {sat, sun, mon, tue, wed, thu, fri};
    week g;
    g.setday(d);
    g.p();
    return 0;
}

Array da:

  • Declares a global string array da of size 7, storing the full day names (“sat”, “sun”, …, “fri”).

Enumeration Days:

  • Defines an enumeration named Days to represent the days of the week with integer values:
    – sat = 1
    – sun (implicitly 2)
    – mon (implicitly 3)
    – …
    – fri (implicitly 7)

Class week:

  • Represents a “week” concept.
    – Member variable:
    * d is an array of Days enumeration type, holding the numerical day values for a week (e.g., sat, sun, …).
    – Member methods:
    * setday(Days w[]): Takes an array of Days enumeration values as input and assigns them to the d member array, copying the day values into the object.
    * p(): Prints the day names and their corresponding numerical values from the d array. It iterates through the array, accessing both the current da string and the d value at the same index to print the pair.

main Function:

  • Creates an array d of Days type and initializes it with sat, sun, …, fri.
  • Instantiates a week object named g.
  • Calls the setday method of g to pass the d array (containing the day values) to the object.
  • Calls the p method of g, which prints the day information in the format “The number of day <day name> = <day value>”.

The code demonstrates the use of enumerations and classes to represent and manage day-of-the-week information in C++.

Static Class Member Static Member Function

Introduction

In C++, “static class members” and “static member functions” introduce class-level elements that are not associated with individual objects of the class.

#include <iostream>
#include <string>
using namespace std;
void f()
{
    static int x = 0;
    x++;
    cout << x << endl;
}
int main()
{
    f();
    f();
    return 0;
}

This C++ program defines a function f() that increments a static integer variable x each time it is called, and then prints the value of x to the standard output. The main() function calls f() twice.

Here’s what the program does:

  • The function f() is defined. It contains a static variable x initialized to 0.
  • Each time f() is called, it increments x by 1 and prints the new value of x.
  • In the main() function, f() is called twice.
  • When f() is called the first time, x is incremented from 0 to 1, and 1 is printed.
  • When f() is called the second time, x is incremented from 1 to 2, and 2 is printed.

Therefore, when you run the program, it should output:

1
2

Here’s what static does in this context:

  1. Preserves Value between Function Calls: When a variable is declared as static inside a function, its value persists between function calls. This means that the variable retains its value even after the function f() exits. In the example, the variable x retains its value between calls to f().
  2. Initialization: Static variables are initialized only once, at the start of the program execution. In this case, the static variable x is initialized to 0 the first time the function f() is called. Subsequent calls to f() do not reinitialize x.
  3. Storage Duration: Static variables have “static storage duration,” meaning they are allocated memory for the entire duration of the program’s execution. This memory is allocated in the data segment of the program.
  4. Scope: The scope of a static variable declared inside a function is limited to that function. It cannot be accessed from outside the function. In this example, x can only be accessed within the f() function.

Static Class Member

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
//define how many objects are created 
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            cout << "Numbers of students constructed: " << count << endl;
        }
}; //end of class
int Student::count = 0;
int main()
{
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

Class Definition (Student):

  • It defines a class Student with private data members name, first, second, final, total, and ID.
  • The count variable is declared as static within the class. This means it is shared among all instances of the Student class, and its value persists across multiple Student objects.

Constructor:

  • The class has a default constructor Student() which initializes the data members with default values.
  • In the constructor, the name is set to “No name”, ID is set to 0, and exam scores are set to 0.
  • Each time a Student object is constructed, the count variable is incremented, and the total number of constructed students is printed.

Static Member Initialization:

  • The count static member is initialized outside the class definition.

Main Function:

  • In the main() function, two Student objects (S1 and S2) are created using the default constructor. The program prints the number of students constructed after each object creation.
  • Then, an array St of three Student objects is created. Again, the program prints the number of students constructed after creating this array.

Output:

Construct 2 objects
Numbers of students constructed: 1
Numbers of students constructed: 2

Construct 3 objects
Numbers of students constructed: 3
Numbers of students constructed: 4
Numbers of students constructed: 5

The count static member variable is used to keep track of the total number of Student objects that have been created. Each time a Student object is constructed (i.e., when the constructor is called), the count is incremented. This allows the program to keep track of how many Student objects have been instantiated across the entire program execution.

Static Member Function

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class Student {
        static int count;
        char name[20];
        int first, second, final, total, ID;
    public:
        static void print_count()
        {
            cout << "Students constructed: " << count << endl;
        }
        Student() //constructor 
        {
            strcpy(name, "No name");
            ID = 0;
            first = second = final = 0;
            count++;
            print_count();
        }
}; //end of class
int Student::count = 0;
int main()
{
    Student::print_count();
    cout << "\nConstruct 2 objects\n";
    Student S1, S2;
    cout << "\nConstruct 3 objects\n";
    Student St[3];
    return 0;
} //end of main

In this updated version of the program, a static member function print_count() has been added to the Student class. Here’s what the static keyword does in this context:

  • Static Member Function: The member function print_count() is declared as static. This means that it belongs to the class itself, rather than to individual instances (objects) of the class. Static member functions do not have access to non-static member variables or functions directly because they are not associated with any particular object.
  • Accessing Static Member Variables: Inside the static member function print_count(), the static member variable count is accessed directly. Since count is also static, it can be accessed without needing an instance of the class.
  • Accessing Static Member Function: Static member functions can be called using the class name followed by the scope resolution operator (::). For example, Student::print_count() calls the print_count() function of the Student class.
  • Usage: In the main() function, Student::print_count() is called before any Student objects are created. This demonstrates that static member functions can be called without the need for object instantiation.
  • Initialization and Increment: Inside the Student constructor, the count variable is incremented each time a new Student object is constructed. The print_count() function is called within the constructor to display the updated count after each object creation.

This program demonstrates the usage of a static member function to access a static member variable and provide functionality associated with the class itself, rather than individual objects of the class.

Constant Object Constant Member Function

Introduction

In C++, a constant variable is a variable whose value cannot be changed once it has been initialized. The value remains constant throughout the execution of the program. Constant variables are declared using the const keyword.

Constant Object

  • Declaration: A constant object is declared by using the const keyword along with the object’s type.
  • Immutable: Once declared as const, the member variables of the object cannot be changed.
  • Calling Member Functions: A constant object can only call constant member functions of its class. This prevents any operations that might modify the object’s internal state.

Constant Member Function

  • Declaration: A member function is declared as constant by appending the const keyword to its declaration and definition.
  • Promise Not to Modify: A constant member function implicitly promises not to modify any of the non-static data members of its class.
  • Enforce Correctness: This helps the compiler enforce correctness and prevents unintentional side effects.

Example

#include <iostream>
using namespace std;
class time {
    private:
        int h, m, s;
    public:
        void print() const //constant function
        {
            cout << "Time = " << h << ":" << m << s << endl;
        }
        time(int i, int j, int k)
        {
            h = i;
            m = j;
            s = k;
        }
};
int main()
{
    const time noon(12, 0, 0); //constant object
    noon.print();

    return 0;
}

In the provided code, both constant functions and constant objects play important roles:

Constant Function (print() const):

  • The member function print() is declared as const, making it a constant member function.
  • A constant member function ensures that it does not modify the state of the object it is called on. It promises not to modify any non-static member variables of the class.
  • In this code, the print() function is responsible for displaying the time stored in the time object. Since it does not modify the object’s state, it is declared as const.
  • By declaring print() as a constant member function, it allows constant objects to call this function.

Constant Object (const time noon(12, 0, 0)):

  • An object named noon of the class time is created and declared as const. This makes noon a constant object.
  • A constant object is an object whose state cannot be modified after initialization. Any attempt to modify its state will result in a compilation error.
  • In this code, the noon object represents a specific time, 12:00:00, and it cannot be changed once created.
  • Constant objects are useful when you want to ensure that the object’s state remains unchanged throughout its lifetime, providing guarantees of immutability and safety.
  • By declaring noon as a constant object, it ensures that the print() function, which is also marked as const, can be called on it. This allows the print() function to access the noon object’s state without fear of modification.

In summary, the constant function (print() const) ensures that it does not modify the object’s state, and the constant object (const time noon(12, 0, 0)) guarantees that its state remains unchanged throughout its lifetime. These concepts work together to enforce immutability and safety in the code.

Friend Function/Friend class

In C++, a friend function or friend class is a feature that allows a function or a class to access private and protected members of another class. This feature breaks encapsulation to some extent but can be useful in specific scenarios where tight coupling between classes is necessary or when implementing certain design patterns.

Friend Function:

A friend function is a regular function that is granted access to private and protected members of a class. To declare a function as a friend of a class, you need to declare it within the class declaration preceded by the friend keyword.

Example 1:

#include <iostream>
using namespace std;
class myClass {
        int a, b;
    public:
        myClass(int i, int j)
        {
            a = i;
            b = j;
        }
        friend int sum(myClass ob);
};
int sum(myClass ob)
{
    return ob.a + ob.b;
}
int main()
{
    myClass o(10, 20);
    cout << sum(o) << endl;
    return 0;
}

In this C++ code snippet, a class called myClass is defined with two private integer members a and b. The class also has a constructor to initialize these members. Additionally, There is a declared friend function sum inside the class.

The sum function takes an object of type myClass as its argument and returns the sum of the private members a and b of that object.

In the main function, There is an object o of type myClass with initial values of 10 and 20, and then a call to the sum function passing this object o as an argument. Finally, the output of the result of the sum function using cout.

Here’s the breakdown of the code execution:

  1. An object o of type myClass is created with values 10 and 20.
  2. The sum function is called with the object o as an argument.
  3. Inside the sum function, the private members a and b of the object ob are accessed due to the friend declaration, and their sum is returned.
  4. The returned sum is then printed using cout.

So, when you run this program, it should output:

30

Example 2:

#include <iostream>
using namespace std;
class CRectangle {
    private:
        int width, height;
        friend CRectangle duplicate(CRectangle);
    public:
        void set_values(int, int);
        int area(void)
        {
            return (width * height);
        }
};
void CRectangle::set_values(int a, int b)
{
    width = a;
    height = b;
}
CRectangle duplicate(CRectangle R)
{
    CRectangle T;
    T.width = R.width * 2;
    T.height = R.height * 2;
    return T;
}
int main()
{
    CRectangle rect, rectb;
    rect.set_values(2, 3);
    cout << "The area before duplicate = " << rect.area() << endl;
    rectb = duplicate(rect);
    cout << "The area after duplicate = " << rectb.area() << endl;
    return 0;
}

This C++ code defines a class CRectangle representing a rectangle. The class has private data members width and height, and two member functions set_values and area.

In the private section, width and height are the dimensions of the rectangle. The set_values function is used to set the values of width and height. The area function calculates and returns the area of the rectangle.

The duplicate function is declared as a friend of CRectangle. This means it has access to the private members of CRectangle.

The set_values function sets the width and height of the rectangle based on the provided parameters.

The duplicate function takes a CRectangle object as a parameter, creates a new CRectangle object T, and assigns T’s width and height to be twice that of the input R’s width and height. It then returns the new rectangle T.

In the main function:

  1. CRectangle objects rect and rectb are created.
  2. rect’s set_values function is called to set its dimensions to 2×3.
  3. The area of rect before duplication is printed.
  4. duplicate function is called with rect as an argument, and the returned rectangle is assigned to rectb.
  5. The area of rectb after duplication is printed.

The output of this program will be:

The area before duplicate = 6
The area after duplicate = 24

Example 3:

#include <iostream>
using namespace std;
class Tri;
class CRectangle {
        int width, height;
    public:
        void set_values(int a, int b) {
            width = a;
            height = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
class Tri {
        int W, H;
    public:
        Tri(int a, int b)
        {
            W = a;
            H = b;
        }
        friend int Sum(Tri T, CRectangle R);
};
int Sum(Tri T, CRectangle R)
{
    return T.W + R.width;
}
int main()
{
    CRectangle r;
    r.set_values(2, 3);
    Tri l(5, 10);
    cout << Sum(l, r) << endl;
    return 0;
}

This C++ code demonstrates the usage of friend functions across different classes. Here’s a breakdown of the code:

Class Declarations:

  • Two classes are declared: CRectangle and Tri.
  • CRectangle has two private data members width and height, and a member function set_values to set these values.
  • Tri has two private data members W and H, and a constructor to initialize them.

Friend Function Declaration:

  • Both classes declare a friend function named Sum. This means that Sum function can access the private members of both CRectangle and Tri.

Friend Function Implementation:

  • The Sum function takes objects of types Tri and CRectangle as arguments and returns the sum of their corresponding private members.
  • In this case, it returns the sum of W from the Tri object and width from the CRectangle object.

Main Function:

  • In the main function, an object r of type CRectangle is created and its set_values function is called to set its dimensions to 2×3.
  • Another object l of type Tri is created with dimensions 5×10.
  • The Sum function is called with objects l and r as arguments, and the result is printed.

Output:

  • Since the Sum function returns the sum of W from Tri and width from CRectangle, the output would be 5 + 2 = 7.

Friend Class:

Friend class is a class that is granted access to the private and protected members of another class. You declare a friend class by preceding its declaration with the friend keyword inside the class that it’s a friend of.

Example 4:

#include <iostream>
using namespace std;
class CSquare;
class CRectangle {
        int width, height;
    public:
        int area(void) {
            return (width * height);
        }
        void convert(CSquare);
};
class CSquare {
    private:
        int side;
    public:
        void set_side(int x)
        {
            side = x;
        }
        friend class CRectangle;
};
void CRectangle::convert(CSquare a)
{
    width = a.side;
    height = a.side;
}
int main()
{
    CSquare sqr;
    CRectangle rect;
    sqr.set_side(4);
    rect.convert(sqr);
    cout << rect.area() << endl;
    return 0;
}

This C++ code demonstrates the usage of friend classes and member functions, particularly in the context of a CRectangle class and a CSquare class.

Class Declarations:

  • Two classes are declared: CRectangle and CSquare.
  • CRectangle has two private data members width and height, and a member function area to calculate its area. It also has a member function convert, which is later defined outside the class.
  • CSquare has one private data member side and a member function set_side to set its value. It declares CRectangle as a friend class.

Friend Class Declaration:

  • CSquare declares CRectangle as a friend class, allowing CRectangle to access its private members.

Member Function Definition:

  • The convert member function of CRectangle is defined outside of the class.
  • It takes a CSquare object as a parameter and assigns its side to both width and height of the CRectangle.

Main Function:

  • In the main function, objects sqr of type CSquare and rect of type CRectangle are created.
  • set_side function of sqr sets its side to 4.
  • convert function of rect is called with sqr as an argument, converting the square into a rectangle.
  • The area of the resulting rect is then printed.

Output:

  • Since the side of the square is 4, after converting it to a rectangle, both width and height of the rectangle become 4. Therefore, the area of the resulting rectangle is 4 * 4 = 16.

Operator Overloading

Operator overloading in C++ is a feature that allows you to redefine the behavior of operators (such as +, -, *, /, etc.) for user-defined types. It enables you to extend the functionality of operators to work with objects of your own classes.

Example 1:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        void add(triangle c1, triangle c2)
        {
            width = c1.width + c2.width;
            height = c1.height + c2.height;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3.add(c1, c2);
    c3.showdata();
    return 0;
}

This C++ code defines a class triangle representing a triangle. The class has private data members width and height, a constructor to initialize them, member functions getdata to input values for width and height, showdata to display the width and height, and add to add two triangles together.

Class Definition:

  • The triangle class is defined with private data members width and height.
  • It has a constructor that initializes width and height with default values of 0.
  • It contains member functions getdata, showdata, and add.

Main Function:

  • In the main function, three triangle objects are created: c1, c2, and c3.
  • c1 is initialized with default values using the default constructor.
  • c2 is initialized with values 3.5 and 1.5 using the parameterized constructor.
  • c3 is created without any initialization.
  • getdata is called for c1 to input values for width and height.
  • add is called for c3 with c1 and c2 as arguments, which adds the corresponding width and height of c1 and c2 and assigns the result to c3.
  • showdata is called for c3 to display the resulting width and height after addition.

Example 2:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle add(triangle c2)
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1.add(c2);
    c3.showdata();
    return 0;
}

In this example, the addition of two triangles is also performed using a member function named add. However, instead of modifying the object on which the function is called, a new triangle object is created inside the add function to store the result of the addition. This new object is then returned from the function, leaving the original objects unchanged.

Example 3:

#include <iostream>
using namespace std;
class triangle
{
    private:
        float width, height;
    public:
        triangle(float a = 0, float b = 0)
        {
            width = a;
            height = b;
        }
        void getdata()
        {
            cout << "Enter width \n";
            cin >> width;
            cout << "Enter height \n";
            cin >> height;
        }
        void showdata()
        {
            cout << "width and height = (" << width << "," << height << ")" << endl;
        }
        triangle operator+(triangle c2) // Overloading the + operator
        {
            triangle c3;
            c3.width = width + c2.width;
            c3.height = height + c2.height;
            return c3;
        }
};
int main()
{
    triangle c1, c2(3.5, 1.5), c3;
    c1.getdata();
    c3 = c1 + c2;  // Using the overloaded + operator
    c3.showdata();
    return 0;
}

This C++ code demonstrates the usage of operator overloading to perform addition between two triangle objects. Let’s break down the code and highlight the differences compared to the previous examples:

Differences compared to previous examples:

  1. Operator Overloading:
    In this example, the + operator is overloaded using a member function named operator+. This allows us to perform addition between two triangle objects using the + operator in a manner similar to built-in types.
    In contrast, the previous examples used member functions (add) to perform addition between objects.
  2. Usage in main Function:
    In the main function, the addition of c1 and c2 is performed using the + operator: c3 = c1 + c2;.
    This syntax is more intuitive and concise compared to calling a separate member function (add).
  3. Return Type:
    The operator+ function returns a triangle object representing the result of the addition.
    In the previous examples, the add functions did not return any value and instead modified one of the objects directly.

this Pointer

In object-oriented programming (OOP) languages like C++, the this pointer is a keyword that is used to refer to the current object within a member function. It is a special pointer that holds the memory address of the current object instance.

Example 1:

#include <iostream>
using namespace std;
class stud {
    public:
        void address() {
            cout << this;
        }
};
int main()
{
    stud a, b, c;
    cout << "The adress of a\t";
    a.address();
    cout << endl << "The adress of b\t";
    b.address();
    cout << endl << "The adress of c\t";
    c.address();
    cout << endl;
    return 0;
}

In this C++ code, we have a class named stud, which contains a member function address(). This member function simply prints the memory address of the current object using the this pointer.

Function of this Pointer:

  • In the address() function of the stud class, this refers to the current object for which the member function is being called.
  • Inside the address() function, cout << this; prints the memory address of the current object.
  • In the main() function, we create three objects a, b, and c of the class stud.
  • We then call the address() function on each object, which prints the memory address of each object.
  • The this pointer ensures that the correct memory address of the current object is printed when address() function is called for each object.

Example 2:

#include <iostream>
using namespace std;
class Student {
        int id;
    public:
        void set_id(int id) {
            this->id = id;
        }
        void print_id() {
            cout << "ID is " << id << endl;
        }
};
int main()
{
    Student St;
    St.set_id(10);
    St.print_id();
    return 0;
}

In this C++ code, we have a class named Student with a private member variable id representing the student’s ID. The class provides two member functions: set_id() and print_id().

Function of this Pointer:

  • In the set_id() member function, the parameter id passed to the function has the same name as the member variable id of the class. To distinguish between them, the this pointer is used.
  • Inside the set_id() function, this->id = id; assigns the value of the parameter id to the member variable id of the current object.
  • The this pointer points to the current object for which the member function is called. It is used to access members of the object.
  • In the main() function, an object St of the class Student is created. The set_id() function is called to set the ID of the St object to 10.
  • Then, the print_id() function is called to print the ID of the St object.

The output of the code will be:

ID is 10

 

Operator Overloading/Unary operator

In C++, operator overloading refers to the ability to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Unary operators are those operators that operate on a single operand. Overloading unary operators allows you to customize their behavior when applied to objects of your own classes.

Purpose of Operator Overloading:

  1. Provide Natural Syntax: Operator overloading allows you to use operators with user-defined types in a way that mimics their usage with built-in types. For example, you can add two objects of a class using the + operator, concatenate strings using the + operator, or increment an object using the ++ operator.
  2. Enhance Readability: By overloading operators, you can make your code more intuitive and readable, as it allows you to express operations in a natural and concise way.

Example 1:

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary. Let’s break down the code:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the unary ++ operator as a member function
    void operator++() {
        x++;
        y++;
    }
};

int main() {
    Unary v(10, 20);
    v++; // Incrementing the object 'v' using overloaded ++ operator
    v.show(); // Displaying the updated values of 'x' and 'y'

    return 0;
}

Explanation:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded using the operator++() member function. This function increments the values of x and y.
  • In the main() function, an object v of the Unary class is created with initial values 10 for x and 20 for y.
  • The ++ operator is applied to the object v using v++. Since it’s a unary operator, it doesn’t require any operand.
  • The overloaded operator++() function increments the values of x and y by one.
  • After the increment operation, the show() function is called to display the updated values of x and y.

The output of the code will be:

11 21

This is because the values of x and y are incremented by 1 after the ++ operator is applied to the object v. Thus, the updated values are displayed as 11 for x and 21 for y.

Example 2:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
};
int main()
{
    Unary v(10, 20), k;
    v++;
    k = v++;
    k.show();
    v.show();

    return 0;
}

This C++ code demonstrates the overloading of the unary ++ operator for a class called Unary, along with the postfix increment operator ++ that takes an additional dummy integer parameter. Let’s break down the code:

  • The Unary class has two private member variables x and y, and a constructor to initialize them. Additionally, it has a member function show() to display the values of x and y.
  • Inside the class definition, the unary ++ operator is overloaded twice:
    1. The operator++() function overloads the prefix ++ operator. It increments the values of x and y and returns the updated object.
    2. The operator++(int) function overloads the postfix ++ operator with an additional dummy integer parameter. It creates a temporary object t and assigns the current object’s values to it. Then, it increments the values of x and y of the current object and returns the temporary object t.
  • In the main() function, two objects v and k of the Unary class are created, with v initialized with values 10 for x and 20 for y.
  • v++ is applied to increment v using the postfix increment operator. This will increment the values of x and y of v and return a temporary object with the original values.
  • k = v++ will first assign the temporary object (with original values) to k and then increment v using the postfix increment operator.
  • The show() function is called to display the values of k and v after the increment operations.

The output of the code will be:

11 21
12 22

Example 3:

#include <iostream>
using namespace std;

class Unary {
    int x, y;
public:
    Unary(int i = 0, int j = 0) {
        x = i;  
        y = j;
    }
    
    void show() {
        cout << x << " " << y << endl;
    }

    // Overloading the prefix ++ operator
    Unary operator++() {
        x++;
        y++;
        return *this;
    }

    // Overloading the postfix ++ operator with an additional dummy integer parameter
    Unary operator++(int) {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }

    // Overloading the unary - operator
    Unary operator-() {
        x = -x;
        y = -y;
        return *this;
    }
};

int main() {
    Unary k(1, 2); // Create an object of the class Unary with initial values 1 and 2
    -k; // Applying unary - operator to object k
    k.show(); // Display the updated values of k

    return 0;
}
  • The operator-() function overloads the unary – operator. It negates the values of x and y by multiplying them by -1 and returns the updated object.
  • In the main() function, an object k of the Unary class is created with initial values 1 for x and 2 for y.
  • The unary – operator is applied to the object k using -k. This will negate the values of x and y of k.
  • Finally, the show() function is called to display the updated values of x and y.

This indicates that the values of x and y of object k have been negated by applying the unary – operator. Therefore, x becomes -1 and y becomes -2.

Example 4:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
};
int main()
{
    Unary x(1, 1);
    if (!x)
        cout << "true";
    else
        cout << "false";

    return 0;
}
  • The operator!() function overloads the logical negation operator !. It returns true if both x and y are equal to 0, indicating that the object is logically false. Otherwise, it returns false.
  • In the main() function, an object x of the Unary class is created with initial values 1 for x and 1 for y.
  • The logical negation operator ! is applied to the object x using !x. If x is logically false (i.e., both x and y are 0), it prints “true”. Otherwise, it prints “false”.

The output of the code will be:

false

Example 5:

#include <iostream>
using namespace std;
class Unary {
        int x, y;
    public:
        Unary(int i = 0, int j = 0) {
            x = i;  y = j;
        }
    void show() { cout << x << " " << y << endl; }
    Unary operator++()
    {
        x++;
        y++;
        return *this;
    }
    Unary operator++(int)
    {
        Unary t;
        t = *this;
        x++;
        y++;
        return t;
    }
    Unary operator-()
    {
        x = -x;
        y = -y;
        return *this;
    }
    bool operator!()
    {
        return (x == 0 && y == 0);
    }
    Unary operator+=(Unary b2)
    {
        x += b2.x;
        y += b2.y;
        return *this;
    }
};
int main()
{
    Unary b(1, 2), b2(3, 3);
    b += b2;
    b.show();
    
    return 0;
}

the operator+=() function overloads the compound assignment operator +=. It adds the corresponding member variables of the current object (this) with the member variables of the passed object (b2) and returns the updated object.

The output of the code will be:

4 5

 

Operator Overloading/Relational Operator

In C++, operator overloading allows you to redefine the behavior of operators such as arithmetic, logical, and relational operators for user-defined types. Relational operators are used to compare values between two operands and determine the relationship between them. Operator overloading for relational operators allows you to define custom comparison behaviors for objects of your own classes.

Purpose of Operator Overloading for Relational Operators:

  1. Custom Comparison: With operator overloading, you can define custom comparison behaviors for objects of your classes. This allows you to compare objects based on specific criteria relevant to your application domain.
  2. Natural Syntax: Overloaded relational operators enable you to use the familiar syntax of relational operators (<, <=, >, >=, ==, !=) with user-defined types. This improves code readability and makes your code more intuitive.

Example:

#include <iostream>
using namespace std;
class Relational {
        int x, y, z;
    public:
        Relational()
        {
            x = y = z = 0;
        }
        Relational(int i, int j, int k)
        {
            x = i;
            y = j;
            z = k;
        }
        int operator==(Relational b)
        {
            return(x == b.x && y == b.y && z == b.z);
        }
};
int main()
{
    Relational a(10, 10, 10), b(10, 10, 10);
    if (a == b)
        cout << "The two objects are equal\n";
    else
        cout << "The two objects are not equal\n";
    
    return 0;
}

This C++ code demonstrates operator overloading for the equality (==) operator in the Relational class.

  • The Relational class represents objects with three integer attributes x, y, and z.
  • The class provides two constructors: one default constructor that initializes all attributes to 0, and another constructor that allows initializing the attributes with provided values.
  • The operator= = function is overloaded inside the class. It takes another Relational object b as a parameter and returns an integer indicating whether the attributes of the two objects are equal. It checks if the x, y, and z attributes of both objects are equal and returns 1 if they are, and 0 otherwise.
  • In the main() function, two Relational objects a and b are created, both initialized with the values (10, 10, 10).
  • The overloaded equality operator == is used to compare objects a and b. If the attributes of both objects are equal, the message “The two objects are equal” is printed; otherwise, the message “The two objects are not equal” is printed.

Introduction to Standard Template Library

The Standard Template Library (STL) is a powerful collection of classes and functions in C++ that provides reusable, generic algorithms, containers, and iterators. It’s an essential component of modern C++ programming and offers a wealth of functionality to simplify and enhance your code.

Key Components of STL:

  1. Containers:
    Containers are objects that store collections of other objects. They provide a way to organize and manipulate data efficiently. STL provides several container classes, each with its unique characteristics:
    – Vector: Dynamic array that automatically adjusts its size.
    – List: Doubly linked list that allows for fast insertions and deletions anywhere in the list.
    – Deque: Double-ended queue that supports fast insertion and deletion at both ends.
    – Set: Collection of unique, sorted elements.
    – Map: Collection of key-value pairs, where each key is unique.
    – Stack: Container with Last-In-First-Out (LIFO) access.
    – Queue: Container with First-In-First-Out (FIFO) access.
  2. Iterators:
    Iterators are objects that allow traversal through the elements of a container. They act as pointers and provide a uniform way to access the elements regardless of the underlying container implementation. There are different types of iterators:
    – Input iterators: Allow reading elements from a container.
    – Output iterators: Allow writing elements to a container.
    – Forward iterators: Support forward traversal.
    – Bidirectional iterators: Support bidirectional traversal (forward and backward).
    – Random access iterators: Support random access to elements (e.g., accessing elements by index).
  3. Algorithms:
    Algorithms are functions that operate on containers through iterators. They perform various operations such as searching, sorting, modifying, and manipulating elements in containers. STL provides a wide range of algorithms for common tasks, including:
    – Sorting: Sort elements in a container.
    – Searching: Search for elements in a container.
    – Transforming: Modify elements in a container based on certain criteria.
    – Copying: Copy elements between containers.
    – Merging: Merge elements from multiple containers into one sorted container.
    And many more…

Types of Container

  1. Simple
    – Pair
  2. Sequence
    – Array
    – Vector
    – Deque
    – List
    – Forward list
  3. Associative
    – Map
    – Multimap
    – Set
    – Multiset
  4. Unordered
    – Unordered set
    – Unordered multiset
    – Unordered map
    – Unordered multimap
  5. Adapter
    – Stack
    – Queue
    – Priority queue

Vector Part 1

Sequence containers in C++ are a category of containers within the Standard Template Library (STL) that store elements in a sequential order. They provide dynamic storage allocation and support various operations for accessing, inserting, and removing elements. Sequence containers are primarily categorized based on how they organize and manage their elements. Here’s an explanation of the commonly used sequence containers:

Arrays

Arrays are considered as a kind of sequence container in C++. However, they are typically categorized separately from other sequence containers like vectors, lists, and deques because of their fixed size nature and the absence of dynamic resizing capabilities.

Vector

Characteristics:

  1. Fast insert/ remove at the end
  2. Slow insert/ remove at the beginning or in the middle
  3. Slow search

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(4);
    v[0] = 10;
    v.push_back(50);

    return 0;
}

This code snippet attempts to create a vector of integers with an initial size of 4 elements, assigns a value to the first element, and then tries to add an additional element using the push_back function. However, there’s a potential issue with the usage of push_back after specifying the initial size.

Let’s analyze the code and discuss the implications:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(4);  // Creates a vector with 4 elements, all initialized to 0

    v[0] = 10;          // Assigns a value of 10 to the first element of the vector

    v.push_back(50);    // Attempts to add an additional element with the value 50
                        // This line may lead to undefined behavior because it's 
                        // appending an element beyond the originally specified size

    return 0;
}

Explanation:

  • The line vector<int> v(4); creates a vector v with an initial size of 4 elements, all initialized to the default value of integers (which is 0).
  • Then, v[0] = 10; assigns a value of 10 to the first element of the vector.
  • However, the subsequent line v.push_back(50); attempts to add an additional element to the vector using push_back. Since the vector was initially sized to contain only 4 elements, appending an element beyond this size may cause undefined behavior. The push_back operation might trigger a reallocation of the vector’s underlying storage, which could lead to memory corruption or other unexpected behavior.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4};  // Initialize vector v with values 1, 2, 3, 4
    vector<int>v2(v);             // Initialize vector v2 as a copy of v
    cout << v2[0];                // Output the first element of v2

    return 0;
}

This code snippet initializes a vector v with four integers {1, 2, 3, 4}, and then attempts to initialize another vector v2 as a copy of v.
The output will be 1, as it prints the first element of v2, which is a copy of v. Therefore, it will print the first element of v, which is 1.

Example 3:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100. This constructor initializes v with 5 elements, each having the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200. This constructor initializes v2 with 6 elements, each having the value 200.
  • cout << v2[0] << endl; prints the first element of v2, which is 200, followed by a newline character.

So, the output of this code will be:

200

Example 4:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5, 100);    // Initialize vector v with 5 elements, each set to the value 100
    vector<int> v2(6, 200);   // Initialize vector v2 with 6 elements, each set to the value 200
    v.swap(v2);               // Swap the contents of v and v2
    cout << v2[0] << endl;    // Output the first element of v2

    return 0;
}

In this code:

  • vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100.
  • vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200.
  • v.swap(v2); exchanges the contents of v and v2, effectively swapping the elements and sizes of the two vectors.
  • cout << v2[0] << endl; attempts to print the first element of v2.

However, after the swap operation, v2 now contains the elements originally in v, and v contains the elements originally in v2. Therefore, attempting to access v2[0] will actually print the first element of the vector that was initially v.

So, the output of this code will be:

100

Example 5:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v;           // Create an empty vector

    v.push_back(10);         // Add 10 to the end of the vector
    v.push_back(20);         // Add 20 to the end of the vector
    v.push_back(30);         // Add 30 to the end of the vector

    cout << v.front() << endl;  // Output the first element of the vector
    cout << v.back() << endl;   // Output the last element of the vector
    cout << v.at(0) << endl;    // Output the element at index 0 of the vector

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v;: Declares an empty vector of integers.
  • v.push_back(10);: Appends the value 10 to the end of the vector v.
  • v.push_back(20);: Appends the value 20 to the end of the vector v.
  • v.push_back(30);: Appends the value 30 to the end of the vector v.
  • cout << v.front() << endl;: Outputs the first element of the vector v using the front() member function. In this case, it prints 10.
  • cout << v.back() << endl;: Outputs the last element of the vector v using the back() member function. In this case, it prints 30.
  • cout << v.at(0) << endl;: Outputs the element at index 0 of the vector v using the at() member function. In this case, it prints 10.

So, the output of this code will be:

10
30
10

Example 6:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(100);   // Create a vector with 100 elements, all initialized to 0

    v.push_back(5);       // Append the value 5 to the end of the vector
    cout << "Size = " << v.size() << endl;        // Output the current size of the vector
    cout << "Capacity = " << v.capacity() << endl; // Output the current capacity of the vector

    return 0;
}

Here’s what each line does:

  • vector<int> v(100);: Creates a vector v with an initial size of 100 elements, all initialized to the default value of int, which is 0.
  • v.push_back(5);: Appends the value 5 to the end of the vector. Since the vector was initialized with a size of 100, but only one element was added, the vector will resize itself as needed to accommodate the new element.
  • cout << “Size = ” << v.size() << endl;: Outputs the current size of the vector using the size() member function. In this case, it prints 101, as there are now 101 elements in the vector.
  • cout << “Capacity = ” << v.capacity() << endl;: Outputs the current capacity of the vector using the capacity() member function. The capacity represents the maximum number of elements that the vector can hold without reallocating memory. In this case, it depends on the implementation, but it’s likely to be greater than or equal to 101, as the vector may allocate additional memory to avoid frequent reallocations when more elements are added.

Example 7:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {1, 2, 3, 4, 5};
    for (size_t i = 0; i < v.size(); i++)
    {
        cout << v[i] << " ";
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {1, 2, 3, 4, 5};: Initializes a vector v with five elements, each containing the values 1, 2, 3, 4, and 5, respectively.
  • for (size_t i = 0; i < v.size(); i++) { … }: This is a traditional for loop that iterates over each element of the vector. It starts with an index i of 0 and continues until i is less than the size of the vector (v.size()).
  • size_t is an unsigned integer type used for representing sizes of objects. It’s commonly used for indices and sizes of containers like vectors.
  • cout << v[i] << ” “;: Within the loop, it prints the value of the element at index i of the vector, followed by a space.

So, the output of this code will be:

1 2 3 4 5

It prints each element of the vector v separated by a space.

 

Deque

Characteristics:

  1. Fast insert/ remove at the beginning and at the end
  2. Slow insert/ remove at the middle
  3. Slow research

List

Characteristics:

  1. Fast insertion and removal of elements from anywhere in the container
  2. Fast random access is not supported. It’s slow at accessing items from the middle
  3. Slow search
  4. Doubly-linked list

Forward List

Characteristics:

  1. First insertion and removal of elements from anywhere in the container
  2. Fast random access isn’t supported
  3. Singly-linked list

Vector Part 2

Iterators

In C++, iterators are objects that provide a way to traverse the elements of a container (such as vectors) in a sequential manner. Iterators act as pointers to elements in the container, allowing you to access and manipulate the elements efficiently. They serve as a bridge between algorithms and data structures, enabling you to perform various operations on container elements without needing to know the underlying implementation details.

For vectors specifically, iterators offer several functionalities:

  1. Accessing Elements: You can use iterators to access individual elements of a vector. Iterators support dereferencing, which allows you to retrieve the value of the element they point to.
  2. Traversal: Iterators provide mechanisms for traversing through the elements of a vector sequentially. You can increment or decrement an iterator to move to the next or previous element, respectively.
  3. Range-Based Operations: Iterators can define ranges within a vector, allowing you to perform operations on subsets of elements. For example, you can specify a range of iterators to indicate a subset of elements to sort or to copy to another container.
  4. Iterator Categories: Iterators in C++ are classified into different categories based on their capabilities and behavior. For vectors, the most commonly used iterator category is the random access iterator, which supports efficient random access to elements using arithmetic operations like addition and subtraction.
  5. Iterator Invalidation: Modifying a vector (e.g., inserting or erasing elements) can invalidate iterators pointing to elements within the vector. It’s essential to be aware of iterator invalidation rules to avoid undefined behavior when working with iterators.

Example 1:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.begin();
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {10, 20, 30, 40};: Initializes a vector v with four integers {10, 20, 30, 40}.
  • vector<int>::iterator it = v.begin();: Declares an iterator it of type vector<int>::iterator and initializes it to point to the beginning of the vector v using the begin() member function.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the first element of the vector) and prints it using cout.

It prints the value of the first element of the vector v, which is 10.

Example 2:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    vector<int>::iterator it = v.end()-1;
    cout << *it;
    return 0;
}

Here’s what each line of the code does:

  • vector<int>::iterator it = v.end() – 1;: Declares an iterator it of type vector<int>::iterator and initializes it to point to the last element of the vector v by subtracting 1 from the result of the end() member function. Note that end() returns an iterator pointing to the position after the last element, so subtracting 1 points it to the last element.
  • cout << *it;: Dereferences the iterator it to access the value it points to (the last element of the vector) and prints it using cout.

It prints the value of the last element of the vector v, which is 40.

Example 3:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over each element of the vector using an iterator it. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator is equal to v.end(), which represents one position past the end of the vector. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
20
30
40

Example 4:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int>v = {10, 20, 30, 40};

for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
{
cout << *it << endl;
}

return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using reverse iterators. It starts with the reverse iterator it pointing to the last element of the vector (v.rbegin()) and continues until the reverse iterator reaches the position before the first element (v.rend()), exclusive. In each iteration, the reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

40
30
20
10

Example 5:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_reverse_iterator it = v.crbegin(); it != v.crend(); it++) { … }: This is a for loop that iterates over the vector elements in reverse order using const reverse iterators. It starts with the const reverse iterator it pointing to the last element of the vector (v.crbegin()) and continues until the const reverse iterator reaches the position before the first element (v.crend()), exclusive. In each iteration, the const reverse iterator is incremented to point to the previous element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const reverse iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v in reverse order, starting from 40 and ending with 10.

Example 6:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {10, 20, 30, 40};
    
    for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++)
    {
        cout << *it << endl;
    }
    
    return 0;
}

Here’s what each line of the code does:

  • for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); it++) { … }: This is a for loop that iterates over the vector elements using const iterators. It starts with the const iterator it pointing to the first element of the vector (v.cbegin()) and continues until the const iterator reaches the position after the last element (v.cend()), exclusive. In each iteration, the const iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the const iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

It prints each element of the vector v on a new line, iterating through the entire vector.

Auto

In C++, the auto keyword is used for type inference, allowing the compiler to automatically deduce the type of a variable based on its initializer. When used with vectors, auto can simplify code by automatically determining the correct type of iterators or elements without explicitly specifying it.

Using auto with vectors can make the code more concise and readable, especially when the iterator or element type is complex or when it’s changed frequently. However, it’s essential to use auto judiciously and ensure that the deduced type is clear and unambiguous.

Example 7:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {5, 10, 15, 20};  // Initialize vector v with four integers

    auto it = v.begin();  // Use auto to deduce the type of the iterator

    // Iterate over the vector elements using the deduced iterator type
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output the value pointed to by the iterator, followed by a newline
    }

    return 0;
}

Here’s what each line of the code does:

  • vector<int> v = {5, 10, 15, 20};: Initializes a vector v with four integers {5, 10, 15, 20}.
  • auto it = v.begin();: Uses auto to deduce the type of the iterator it. In this case, it deduces that it is of type vector<int>::iterator, pointing to the beginning of the vector v.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using the deduced iterator type. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
10
15
20

Example 8:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.insert(v.begin()+1, 12);
    v.insert(v.end()-1, 17);
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.insert(v.begin() + 1, 12);: Inserts the value 12 into the vector v at the position after the first element (index 1).
  • v.insert(v.end() – 1, 17);: Inserts the value 17 into the vector v at the position before the last element. Since v.end() points to one past the last element, subtracting 1 positions the insertion point before the last element.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5
12
10
15
17
20

Example 9:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin());: Removes the first element from the vector v using the erase() method. Since v.begin() points to the first element, this operation removes that element from the vector.
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

10
15
20

Example 10:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v = {5, 10, 15, 20};
    v.erase(v.begin()+1, v.end());
    
    
    for (auto it = v.begin(); it != v.end(); it++)
        cout << *it << endl;
    
    return 0;
}

Here’s what each part of the code does:

  • v.erase(v.begin() + 1, v.end());: Removes elements from the second element (index 1) until the end of the vector using the erase() method with iterators defining the range. The range is specified from v.begin() + 1 (the iterator pointing to the second element) to v.end() (the iterator pointing one past the last element).
  • for (auto it = v.begin(); it != v.end(); it++) { … }: This is a for loop that iterates over the remaining vector elements using auto for type inference. It starts with the iterator it pointing to the beginning of the modified vector (v.begin()) and continues until the iterator reaches the position after the last remaining element (v.end()), exclusive. In each iteration, the iterator is incremented to point to the next element (it++).
  • cout << *it << endl;: Within the loop, it dereferences the iterator it to access the value of the remaining element it points to and prints it using cout, followed by a newline (endl).

So, the output of this code will be:

5

Example 11:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int>v(10);
    
    for (int i = 0; i <10; i++)
        v[i] = i;
    
    cout << "Vector size initially: " << v.size();
    cout << "\nVector elemens are: ";
    for (int i = 0; i <10; i++)
        cout << v[i] << " ";
        
    v.resize(5);
    cout << "\n\nVector size after resize(5): " << v.size();
    v.shrink_to_fit();
    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(10);: Initializes a vector v with size 10, containing default-initialized elements (all elements are initialized to zero in this case).
  • Assigns values to the elements of the vector using a loop.
  • Outputs the initial size of the vector using v.size().
  • Outputs the elements of the vector using a loop.
  • Resizes the vector to size 5 using v.resize(5). This operation reduces the size of the vector to 5, and any excess elements are removed from the vector.
  • Outputs the size of the vector after resizing.
  • Calls v.shrink_to_fit() to reduce the capacity of the vector to match its size.

Note: shrink_to_fit() is a non-binding request to reduce the capacity of the vector to fit its size but does not guarantee that the capacity will actually be reduced. The implementation may choose to ignore the request.

 

Vector Part 3

Example 1:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v(5);  // Initialize vector v with size 5
    int n = 0;

    // Prompt the user to enter vector elements
    cout << "Enter Vector Elements:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cin >> v[i];  // Read input into vector element at index i
        
        // Check if we're at the end of the vector
        if (i == v.size() - 1) {
            cout << "If you want to resize the list, enter the new size. Enter -1 to finish: ";
            cin >> n;
            if (n == -1)
                break;
            else
               v.resize(n);  // Resize the vector to the new size entered by the user
        }
    }

    // Output the elements of the vector
    cout << "Vector elements are:\n";
    for (size_t i = 0; i < v.size(); i++) {
        cout << v[i] << endl;  // Output each element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v(5);: Initializes a vector v with size 5, containing default-initialized elements (all elements are initialized to zero in this case).
  • Prompts the user to enter vector elements.
  • Reads input from the user into the vector elements using a loop. After reading the last element, the code prompts the user to either resize the vector or exit the loop by entering -1.
  • If the user enters a new size, the vector is resized accordingly using v.resize(n).
  • Outputs the elements of the vector after the loop ends.

This code allows the user to dynamically resize the vector during input and then displays the elements of the vector.

Example 2:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some unsorted integers

    sort(v.begin(), v.end());  // Sort the elements of the vector in ascending order

    // Output the sorted elements of the vector
    for (auto it : v) {
        cout << it << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in an unsorted order.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm. The sort function requires two iterators specifying the range to be sorted, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).
  • for (auto it : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in ascending order.
  • cout << it << endl;: Within the loop, it prints each element it of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
3
5
7

It prints each element of the sorted vector v in ascending order, one element per line.

Example 3:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    sort(v.rbegin(), v.rend());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}

Here’s what each part of the code does:

  • sort(v.rbegin(), v.rend());: Sorts the elements of the vector v in descending order using the std::sort algorithm with reverse iterators. The sort function requires two iterators specifying the range to be sorted, which are v.rbegin() (pointing to the last element, treated as the first for sorting) and v.rend() (pointing to one before the first element, treated as the last for sorting).

So, the output of this code will be:\

7
5
3
2
1
0

It prints each element of the sorted vector v in descending order, one element per line.

Example 4:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};
    reverse(v.begin(), v.end());
    for (auto it:v)
    {
        cout << it << endl;
    }

    return 0;
}
  • reverse(v.begin(), v.end());: Reverses the elements of the vector v using the std::reverse algorithm. The reverse function requires two iterators specifying the range to be reversed, which are v.begin() (pointing to the first element) and v.end() (pointing to one past the last element).

So, the output of this code will be:

3
0
7
2
1
5

It prints each element of the reversed vector v, one element per line.

Example 5:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find and output the minimum element in the vector
    cout << *min_element(v.begin(), v.end()) << endl;

    // Find and output the maximum element in the vector
    cout << *max_element(v.begin(), v.end()) << endl;

    // Find and output the minimum element in the vector excluding the last two elements
    cout << *min_element(v.begin(), v.end() - 2) << endl;

    return 0;
}

Here’s what each part of the code does:

  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers in the given order.
  • cout << *min_element(v.begin(), v.end()) << endl;: Finds the minimum element in the vector v using the std::min_element algorithm. The min_element function returns an iterator pointing to the minimum element, and * dereferences this iterator to obtain the value of the minimum element. The minimum element is then printed followed by a newline.
  • cout << *max_element(v.begin(), v.end()) << endl;: Similar to above, this line finds and prints the maximum element in the vector v.
  • cout << *min_element(v.begin(), v.end() – 2) << endl;: Finds the minimum element in the vector v excluding the last two elements. The range used for finding the minimum element is from v.begin() to v.end() – 2 (excluding the last two elements). The minimum element is then printed followed by a newline.

So, the output of this code will be:

0
7
1

It prints the minimum element, maximum element, and minimum element excluding the last two elements of the vector v, each followed by a newline.

Example 6:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<int>v = {5, 1, 2, 7, 0, 3};

    auto pair = minmax_element(v.begin(), v.end());
    cout << *pair.first << endl;
    cout << *pair.second << endl;

    return 0;
}

Here’s what each part of the code does:

  • auto pair = minmax_element(v.begin(), v.end());: Finds both the minimum and maximum elements in the vector v using the std::minmax_element algorithm. This function returns a pair of iterators, where the first iterator points to the minimum element and the second iterator points to the maximum element.
  • cout << *pair.first << endl;: Outputs the value of the minimum element by dereferencing the iterator pair.first.
  • cout << *pair.second << endl;: Outputs the value of the maximum element by dereferencing the iterator pair.second.

So, the output of this code will be:

0
7

It prints the minimum and maximum elements of the vector v, each followed by a newline.

Example 7:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Find the minimum element in the vector
    auto it = min_element(v.begin(), v.end());

    // Sort the elements of the vector up to (but not including) the minimum element
    sort(v.begin(), it);

    // Output the sorted elements of the vector
    for (auto i : v) {
        cout << i << endl;  // Output each sorted element followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • auto it = min_element(v.begin(), v.end());: Finds the minimum element in the vector v using the std::min_element algorithm. This function returns an iterator pointing to the minimum element.
  • sort(v.begin(), it);: Sorts the elements of the vector v up to (but not including) the minimum element found by min_element. It uses the std::sort algorithm with a range specified by iterators, from v.begin() to it. This sorts the elements before the minimum element.
  • for (auto i : v) { … }: This is a range-based for loop that iterates over the sorted vector v. It iterates through each element of the vector v in sorted order.
    cout << i << endl;: Within the loop, it prints each sorted element i of the vector followed by a newline using cout.

So, the output of this code will be:

0
1
2
5
7

It prints each element of the vector v up to the minimum element, sorted in ascending order, each followed by a newline.

Example 8:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool GreaterThanThree(int i) {
    return i > 3;
}

int main() {
    vector<int> v = {5, 1, 2, 7, 0, 3};  // Initialize vector v with some integers

    // Sort the elements of the vector in ascending order
    sort(v.begin(), v.end());

    // Find the first element greater than 3 using find_if with GreaterThanThree as the predicate
    auto it = find_if(v.begin(), v.end(), GreaterThanThree);

    // Output all elements greater than 3
    for (; it != v.end(); it++) {
        cout << *it << endl;  // Output each element greater than 3 followed by a newline
    }

    return 0;
}

Here’s what each part of the code does:

  • bool GreaterThanThree(int i): Defines a predicate function GreaterThanThree that returns true if the input integer i is greater than 3.
  • vector<int> v = {5, 1, 2, 7, 0, 3};: Initializes a vector v with six integers.
  • sort(v.begin(), v.end());: Sorts the elements of the vector v in ascending order using the std::sort algorithm.
  • auto it = find_if(v.begin(), v.end(), GreaterThanThree);: Finds the first element greater than 3 in the sorted vector v using the std::find_if algorithm with the GreaterThanThree predicate function.
  • for (; it != v.end(); it++) { … }: This is a for loop that iterates over the elements from the first element greater than 3 until the end of the vector. It outputs each element greater than 3 followed by a newline using cout.

So, the output of this code will be:

5
7

It prints each element of the vector v that is greater than 3, each followed by a newline.

Example 9:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool GreaterThanThree(int i)
{
    return i > 3;
}
int main()
{
    int arr[] = {10, 20, 30, 40, 50, 60, 70};
    vector<int> v(7);
    copy(arr, arr + 7, v.begin());
    cout << "myvector contains: ";
    for (auto it:v)
        cout << it << " ";
    return 0;
}

Here’s what each part of the code does:

  • int arr[] = {10, 20, 30, 40, 50, 60, 70};: Initializes a C-style array arr with seven integers.
  • vector<int> v(7);: Initializes a vector v with size 7.
  • copy(arr, arr + 7, v.begin());: Copies elements from the C-style array arr to the vector v using the std::copy algorithm. The copy function requires three parameters: the beginning and end iterators of the source range (here, arr and arr + 7 representing the whole array), and the beginning iterator of the destination range (here, v.begin()).
  • cout << “myvector contains: “;: Outputs a message indicating the start of the output.
  • for (auto it : v) cout << it << ” “;: This is a range-based for loop that iterates over the elements of the vector v. It outputs each element of the vector followed by a space.

So, the output of this code will be:

myvector contains: 10 20 30 40 50 60 70

Example 10:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    vector<int> to_vector(15);
    copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());
    cout << "to_vector contains: ";
    for (auto i: to_vector)
        cout << i << " ";
    return 0;
}

Here’s what each part of the code does:

  • vector<int> from_vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};: Initializes a source vector from_vector with ten integers.
  • vector<int> to_vector(15);: Initializes a target vector to_vector with size 15.
  • copy_backward(from_vector.begin(), from_vector.end(), to_vector.end());: Copies elements from the source vector from_vector to the target vector to_vector in reverse order using the std::copy_backward algorithm. The copy_backward function requires three parameters: the beginning and end iterators of the source range (here, from_vector.begin() and from_vector.end() representing the whole vector), and the end iterator of the destination range (here, to_vector.end()).
  • cout << “to_vector contains: “;: Outputs a message indicating the start of the output.
  • for (auto i : to_vector) cout << i << ” “;: This is a range-based for loop that iterates over the elements of the target vector to_vector. It outputs each element of the target vector followed by a space.

So, the output of this code will be:

to_vector contains: 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10

It prints each element of the target vector to_vector, which contains the elements of the source vector from_vector copied in reverse order, followed by a space. The initial elements of to_vector that were not overwritten by the copy operation are left unchanged (default-initialized to 0 in this case).

Example 11:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3, 4, 5};  // Initialize a vector v with five integers

    // Copy elements from the vector v to the standard output (cout)
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

Here’s what each part of the code does:

  • copy(v.begin(), v.end(), ostream_iterator<int>(cout, ” “));: Copies elements from the vector v to the standard output (cout) using the std::copy algorithm and std::ostream_iterator. The copy function requires three parameters: the beginning and end iterators of the source range (here, v.begin() and v.end() representing the whole vector), and the output iterator (here, ostream_iterator<int>(cout, ” “)) that writes each copied element to the standard output with a space separator.

So, the output of this code will be:

1 2 3 4 5

Properties of vector

  1. Add -> Back -> O(1):
    This line indicates that adding an element to the back (end) of a vector has a time complexity of O(1), meaning it’s a constant-time operation. Vectors have dynamic memory allocation, and adding an element to the back typically involves appending the element to the end of the underlying contiguous memory block, which can be done in constant time.
  2. Delete -> Back -> O(1):
    Deleting an element from the back (end) of a vector also has a time complexity of O(1), which means it’s a constant-time operation. Removing the last element usually involves decrementing the size of the vector, and no reallocation or shifting of elements is required.
  3. Add -> Any Where -> O(N):
    Adding an element anywhere except the back of the vector, such as at the front or in the middle, has a time complexity of O(N). This is because inserting an element at an arbitrary position may require shifting all subsequent elements to make room for the new element, which takes linear time proportional to the number of elements shifted.
  4. Delete -> Any Where -> O(N):
    Similarly, deleting an element from anywhere except the back of the vector also has a time complexity of O(N). Removing an element from an arbitrary position may require shifting all subsequent elements to fill the gap left by the deleted element, which also takes linear time proportional to the number of elements shifted.
  5. Access -> [] – at() -> O(1):
    Accessing an element in a vector by index using the square brackets ([]) operator or the at() member function has a time complexity of O(1). This means that accessing any element in the vector takes constant time regardless of the size of the vector. Vectors provide constant-time random access because they store elements in a contiguous memory block, allowing for direct access to any element by its index.
  6. Search -> find() -> O(log N):
    Searching for an element in a sorted vector using the std::find() algorithm has a time complexity of O(log N) when the vector is sorted. This is because std::find() performs a binary search on the sorted vector, which has a logarithmic time complexity. However, it’s important to note that if the vector is not sorted, the time complexity of finding an element using std::find() would be O(N), as it performs a linear search.

Advantages:

Implemented as dynamic arrays

Drawbacks:

  1. Expensive reallocation
  2. Requires Contiguous Memory

Complexity

Introduction:

Complexity in data structures is a fundamental concept in computer science that helps us analyze the performance and efficiency of algorithms. It allows us to quantify the resources (such as time and memory) required by an algorithm to solve a problem as the input size grows. In this article, we’ll explore the basics of complexity in data structures, including time complexity and space complexity, and how they impact algorithm design and analysis.

In search algorithms, analyzing the efficiency requires considering different potential scenarios. This helps us understand how the algorithm performs under different circumstances. Here, we’ll explore base case, average case, and worst case along with their complexity notation:

  1. Base Case (Omega notation):
    Denotes the simplest input where the algorithm terminates in the least number of steps.
    Notation: Varies depending on the algorithm. Often denoted by O(1) which signifies constant time, independent of input size.
  2. Average Case (Theta notation):
    Represents the performance expected on average when considering all possible inputs with equal probability.
    Notation: Depends on the algorithm’s design and data distribution. For example, linear search has an average case of O(n/2), meaning it takes half the comparisons, on average, to find an element in a list.
  3. Worst Case (Big O notation):
    Represents the most challenging scenario, requiring the maximum number of steps.
    Notation: Again, depends on the algorithm. Linear search’s worst case is O(n), signifying it may need to compare all elements if the target is not present or at the end.
  • Further Note:
    – Complexity notation uses symbols like O, Ω, and Θ to represent how the execution time grows with input size (Big O Notation, Big Omega Notation, and Big Theta Notation respectively).
    – These representations provide an idealized theoretical understanding of the algorithm’s efficiency, not always guaranteeing exact execution times.

Big O notation

Big O notation is a mathematical tool used in computer science to describe the upper bound of how an algorithm’s execution time or space complexity grows as the input size increases. In simpler terms, it helps us understand how efficiently an algorithm performs as it deals with larger and larger datasets.

Here are some key points about Big O notation:

What it describes:

Big O notation focuses on the limiting behavior of a function (usually representing the algorithm’s complexity) as the input size tends towards infinity. It ignores constants and lower-order terms, providing a general idea of the algorithm’s efficiency, not the exact execution time.

Key notations:

  • O(n): This is the most common notation, meaning the function grows linearly with the input size (n). Doubling the input roughly doubles the execution time. Examples include searching an unsorted list (linear search) and iterating through all elements of an array.
  • O(log n): This signifies logarithmic growth, which is much faster than linear. Doubling the input only increases the execution time by a constant amount. Binary search is a classic example.
  • O(1): This represents constant time complexity, meaning the execution time is independent of the input size. Accessing an element directly in an array by its index is O(1).
  • O(n^2): This denotes quadratic growth, where the execution time increases quadratically with input size. Nested loops can often lead to O(n^2) complexity.
  • O(k^n): This represents exponential growth, which is generally undesirable due to its rapid increase in execution time with even small input size.

Interpreting Big O:

  • Lower values (O(1), O(log n)) are generally better as they indicate faster algorithms that scale well with larger inputs.
  • Higher values (O(n^2), O(k^n)) can be problematic for large datasets as they lead to significant performance bottlenecks.

Big O is not the only complexity measure:

While Big O focuses on upper bounds, there are other notations like Omega (Ω) for lower bounds and Theta (Θ) for exact bounds.

Example 1:

sum; // n = 5
for (i = 1; i <= n; i++)
sum = sum + 1;

This code calculates the sum of numbers from 1 to n using a for loop. The loop iterates n times, and within each iteration, it performs a constant-time addition operation (sum = sum + 1).

Therefore, the time complexity of this code is O(n). This means that the execution time of the code grows linearly with the input size n. In other words, as the value of n increases, the time it takes for the code to run will also increase, but at a proportional rate.

Here’s a table summarizing the time complexity analysis:

Step Description Time Complexity
Initialization Declare variables sum and i O(1)
Loop Iterate n times O(n)
Increment Add 1 to sum in each iteration O(n)
Total O(n)

Overall, the code has a linear time complexity, which is considered efficient for many algorithms.

Introduction to Stack

Introduction:

In the realm of computer science and programming, understanding data structures is fundamental. One such essential data structure is the stack. In this article, we’ll delve into what stacks are, how they work, their operations, and their applications in programming.

What is a Stack?

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. Imagine a stack of plates in a cafeteria; you can only take the top plate off the stack. Similarly, in a stack data structure, elements can only be added or removed from the top.

How Does a Stack Work?

A stack has two primary operations: push and pop.

  • Push: Adds an element to the top of the stack.
  • Pop: Removes the top element from the stack.

Additionally, stacks typically support other operations like peek (to view the top element without removing it) and isEmpty (to check if the stack is empty).

Stack Implementation:

Stacks can be implemented using arrays or linked lists.

  • Array Implementation: In this approach, a fixed-size array is used to store the stack elements. Push and pop operations modify the top index of the array.
  • Linked List Implementation: Here, a linked list is used to implement the stack. Each node in the linked list represents an element, and the top of the stack is the head of the list.

Stack Operations:

Let’s look at the stack operations in detail:

  • Push: Adds an element to the top of the stack. The new element becomes the top element, and the stack size increases by one.
  • Pop: Removes the top element from the stack. The element is returned (or simply removed), and the stack size decreases by one.
  • getTop: Returns the top element of the stack without removing it.
  • isEmpty: Checks if the stack is empty. Returns true if the stack is empty, and false otherwise.

Applications of Stacks:

Stacks find applications in various areas of computer science and programming, including:

  • Function Call Stack: Used to manage function calls and local variables in programming languages.
  • Expression Evaluation: Used to evaluate arithmetic expressions, infix-to-postfix conversion, and solving postfix expressions.
  • Undo Mechanism: Supports the undo operation in text editors and graphic design software.
  • Backtracking: Used in algorithms like depth-first search (DFS) to explore all possible paths in a graph.

Conclusion:

In conclusion, stacks are simple yet powerful data structures that play a crucial role in many programming tasks. Understanding how stacks work and their applications can significantly enhance a programmer’s problem-solving abilities. Whether you’re a beginner or an experienced programmer, mastering stacks is essential for building efficient and robust software systems.

 

Stack Implementation

This code defines a simple stack class with basic operations like push, pop, getTop, and print. Here’s a breakdown of the code:

#include <iostream>
using namespace std;

const int MAX_SIZE = 100;

class Stack {
private:
    int top;            // Index of the top element in the stack
    int item[MAX_SIZE]; // Array to store stack elements

public:
    // Constructor: Initializes top to -1 (empty stack)
    Stack() : top(-1) {}

    // Function to push an element onto the stack
    void push(int Element) {
        if (top >= MAX_SIZE - 1) {
            cout << "Stack is full on push" << endl;
        } else {
            top++;
            item[top] = Element;
        }
    }

    // Function to check if the stack is empty
    bool isEmpty() {
        return top < 0;
    }

    // Function to pop an element from the stack
    void pop() {
        if (isEmpty()) {
            cout << "Stack is empty on pop" << endl;
        } else {
            top--;
        }
    }

    // Function to get the top element of the stack
    void getTop(int& stackTop) {
        if (isEmpty()) {
            cout << "Stack is empty on getTop" << endl;
        } else {
            stackTop = item[top];
            cout << stackTop << endl;
        }
    }

    // Function to print the elements of the stack
    void print() {
        cout << "[";
        for (int i = top; i >= 0; i--) {
            cout << item[i] << " ";
        }
        cout << "]" << endl;
    }
};

int main() {
    Stack s;

    // Push elements onto the stack
    s.push(5);
    s.push(10);
    s.push(15);
    s.push(20);

    // Print the stack
    s.print();

    // Get and print the top element of the stack
    int y = 0;
    s.getTop(y);

    // Pop an element from the stack
    s.pop();

    // Push another element onto the stack
    s.push(7);

    // Print the stack again
    s.print();

    return 0;
}

Explanation:

  • The Stack class implements a stack using an array named item. It has member functions for push, pop, getTop, isEmpty, and print.
  • In the push function, if the stack is not full, it increments the top index and adds the element to the item array at the top index.
  • The isEmpty function checks if the stack is empty by comparing the top index with -1.
  • The pop function decrements the top index if the stack is not empty.
  • The getTop function retrieves the top element of the stack and stores it in the stackTop parameter.
  • The print function prints the elements of the stack from top to bottom.
  • In the main function, a Stack object s is created and various operations like push, pop, getTop, and print are performed on it, demonstrating the usage of the stack.

 

Stack Using Linked List(Linked Stack)-Part 1

Introduction

We’ve covered the concepts of a stack and a stack implemented using arrays. Now, let’s explore the implementation of a stack using pointers and discuss why it’s considered a superior approach.

You might be wondering why we need to discuss this alternative when we’ve already looked at stack implementations using arrays. Can’t we just stick to arrays?

The reason for exploring stack implementation with pointers is to address potential limitations we might encounter with array-based implementations, particularly regarding size constraints. By utilizing pointers, we can effectively circumvent such issues, ensuring a more flexible and robust solution for managing data within a stack structure.

Using pointers to implement a stack involves dynamically allocating memory for the stack elements and manipulating pointers to manage the stack structure. This approach is particularly useful when the size of the stack is not known beforehand or when memory efficiency is a concern.

Node Structure

A “node” refers to a fundamental building block used in many data structures, including linked lists, trees, graphs, and more. A node is a structure that contains two main components:

  1. Data: This component holds the actual value or element that the node represents. It could be of any data type depending on the application.
  2. Next Pointer (or Link): This component is a reference or pointer to the next node in the sequence. It establishes the connection between nodes in the data structure.

These code snippets define a basic node structure in different programming languages:

  • C++:
    struct Node {
        Type item;
        Node* next;
    };
    

    In C++, struct is used to define a structure named Node. It contains two members:

    – item: A variable of type Type to store data.
    – next: A pointer to another Node, indicating the next node in the sequence.

  • Java:
    class Node {
        Type item;
        Node next;
    }
    

    In Java, class is used to define a class named Node. Similarly, it has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • C#:
    class Node {
        Type item;
        Node next;
    }
    

    This is similar to Java. In C#, class is used to define a class named Node, and it also has two members:

    – item: A variable of type Type to store data.
    – next: An object of type Node, representing the next node in the sequence.

  • Python:
    class Node:
        def __init__(self):
            self.item = None
            self.next = None
    

    In Python, a class named Node is defined. The __init__ method is a constructor used to initialize objects of the class. Inside the constructor:

    – self.item is initialized to None, indicating that it stores data.
    – self.next is initialized to None, indicating that it refers to the next node in the sequence.

stackTop

stackTop typically refers to the top element of a stack data structure. In the context of a stack, it is a variable or pointer that points to the topmost element of the stack, or in other words, the most recently added element.

To assign the value of stackTop to the next member of a node:

  • C++:
    newNode is a pointer to a node, and stackTop is presumably another pointer to a node. This line assigns the value of stackTop to the next pointer of the newNode, effectively linking newNode to the node pointed to by stackTop.

    newNode->next = stackTop;
    
  • Java, C#, Python:
    newNode is an object of type Node, and stackTop is also an object of type Node. This line assigns the reference of the object referred to by stackTop to the next field of the newNode.

    newNode.next = stackTop; // Java and C#
    
    newNode.next = stackTop // Python

To assigns the value of newNode to stackTop:
C++, Java, C#, Python:

stackTop = newNode

stackTop is a pointer to the top element of a stack implemented using pointers or dynamic memory allocation. stackTop = newNode would update stackTop to point to the newly created node newNode. This effectively makes newNode the new top element of the stack.
To creates a copy of stackTop we use the statement:

temp = stackTop

Why do we do that?

Creating a copy of stackTop (temp) allows you to safely manipulate and access the top element of the stack without affecting the original pointer, reference, or value. It provides flexibility and ensures that the original data remains intact for future use.

A Pointer-Base Implementation of the ADT Stack(linked stack) main Functions:

  • push(Type newItem)
  • pop()
  • pop(Type& stackTop)
  • getTop()
  • display()
  • isEmpty()

Introduction

Java Programming Language

Java is a class-based, object-oriented programming language. It is widely used for developing various types of applications, ranging from simple desktop utilities to complex enterprise-level systems.

Java is available for most operating systems (Write once run anywhere).

Applications of Java with Real-world Examples

  • Applications for Mobiles.
  • Desktop GUI Applications.
  • Web Applications.
  • Gaming Applications.
  • Enterprise Applications.
  • Security.
  • Scientific Applications.
  • Embedded Systems.
  • Big Data Technologies.
  • Distributed Applications.
  • Cloud-based Applications.
  • Web servers and Application servers.
  • Software Tools.

Why do we need to learn programming languages?

There are many reasons why learning a programming language like Java can be valuable, even if you don’t plan to become a professional programmer. Here are just a few:

  • Directly shape the digital landscape: Java is used to build countless websites and mobile apps, from your favorite social media platforms to online banking tools. Learning Java empowers you to be more than just a user; you can become a creator, shaping the digital experiences of others.
  • Boosts problem-solving and critical thinking: Programming helps you develop logical thinking skills and the ability to break down complex problems into smaller, solvable steps. This translates well to other areas of life, from tackling schoolwork to making everyday decisions.
  • Opens career doors: While not essential for every job, programming skills are increasingly sought-after across various industries. Even basic knowledge can give you an edge in many fields, from marketing and finance to data science and education.
  • It’s simply fun and rewarding! There’s a unique satisfaction in seeing your code come to life and create something functional or even beautiful. The learning process itself can be challenging and rewarding, fostering a sense of accomplishment and growth.

We also need to know how to communicate with computers, and to do so we have something called binary system which represents data and instructions using only two symbols: 0 and 1. This system is the foundation of digital computing because electronic devices, such as computers and microprocessors, interpret and process information in binary format.

As a programmer, you write source code to implement specific functions, such as generating text. This source code is written using a specific syntax. For example, in Java, you might write System.out.print(“Java”). This line of code is understandable to humans and is considered a high-level language representation.

However, before the machine can understand and execute this code, it must undergo several steps to translate it into a form it can process. Firstly, the code is passed through a Java compiler (javac), which checks the syntax and transforms the source code into bytecode. Bytecode is a low-level representation of the code that is platform-independent and can be executed by any system with a Java Virtual Machine (JVM).

Next, the bytecode is interpreted by the JVM, which acts as an interpreter. The JVM translates the bytecode into machine code instructions that the underlying operating system can understand and execute. This process allows Java programs to run on various operating systems without modification, making it a key feature of the Java language.

The Java Programming Language Platforms

  • Java Platform, Standard Edition (Java SE)
    – Desktop applications.
  • Java Platform, Enterprise Edition (Java EE)
    – Web applications, Server applications.
  • Java Platform, Micro Edition (Java ME)
    – Mobile applications, Gaming applications.
  • Java FX
    – Platform for desktop, mobile and embedded systems. Built on Java and fully featured toolkit for developing rich client applications.

Installing the Java Development Tools

Download Java Development Kit

To download Java Development Kit (JDK) for Java programming, follow these steps:

  1. Open your web browser and search for “download JDK for Java” on Google. Visit the official Oracle website because Java is owned by Oracle. You’ll be directed to the Java SE Downloads page.
  2. On the Java SE Downloads page, choose the JDK version that corresponds to your operating system. Options are typically available for Windows, macOS, and Linux.
  3. Accept the Oracle Technology Network License Agreement for Oracle Java SE to proceed with the download. Read through the terms and conditions and accept them if you agree.
  4. Click on the download link to start downloading the JDK installer file. The file format will be .exe for Windows, .dmg for macOS, and .tar.gz for Linux.
  5. Once the download is complete, locate the downloaded installer file and run it. Follow the on-screen instructions to install the JDK on your system.

Setting up development environment

Now, to set up your development environment:

  1. Download an Integrated Development Environment (IDE) for Java. Again, perform a Google search for “IDE for Java” and consider downloading Apache NetBeans, which is a user-friendly IDE for Java development. If you don’t want to download the ide you could work with us right now with an online compiler and we recommend ideone.com.
  2. Search for “download NetBeans for Java” on Google. Look for the Apache NetBeans release and download it.
  3. Once the download is complete, you can find the downloaded NetBeans IDE on your device. Navigate to the “Start” menu and click on it to open the NetBeans IDE.
  4. To start your first project in NetBeans, click on “File” > “New Project” > “Java” > “Java Application”. Choose a name for your project (e.g., “FirstProject”) and select your desired location. Click “Finish” to create the project.
  5. In the project window, navigate to the “Source Packages” folder. Right-click on the folder’s content and select “New” > “Java Class”. Name the class using capital letters for each word with no spaces (e.g., “NewClass”). Make sure the class name matches the name of the Java file. Click “Finish” to create the class.

By following these steps, you’ll have successfully downloaded and installed the JDK for Java development, set up the Apache NetBeans IDE, and created your first Java project. You’re now ready to start coding in Java!

Syntax Rules

Here are the rules of Java syntax:

  1. Reserved Words: Certain words in Java are reserved for specific purposes and cannot be used as identifiers (e.g., class, public, static). These words are known as reserved words or keywords and are highlighted in blue.
  2. Code Blocks: All code blocks in Java must be enclosed within curly brackets {}. This includes class definitions, method definitions, loops, and conditional statements.
  3. Main Method: The starting point of a Java program is the main method. It must be declared as public static void main(String[] args) and should always be written as shown below:
    public static void main(String[] args) {
        // Code goes here
    }
    
  4. Semicolons: Semicolons (;) are used to terminate statements in Java. Every statement must end with a semicolon.
  5. Example Program:
    public class MyFirstProgram {
        public static void main(String[] args) {
            System.out.print("Hello");
        }
    }
    

     

  6. The System.out.print() method is a function in Java that is used to display output to the console. Here’s a breakdown of its components:
    – System: System is a class in Java’s java.lang package. It provides access to the standard input, output, and error streams of the system.
    – out: out is a static member of the System class. It represents the standard output stream, which is typically the console or terminal where you see text output when running a Java program.
    – print(): print() is a method of the out object. It is used to display text or other data on the standard output stream without advancing to the next line. Whatever is passed as an argument to the print() method will be displayed on the console.
    For example:

    System.out.print("Hello");
    

    This line of code will display “Hello” on the console.

  7. Case Sensitivity: Java is case-sensitive, meaning that uppercase and lowercase letters are treated as distinct. For example, “hello” and “Hello” are considered different identifiers.

Types of Errors

In Java, errors can generally be categorized into three main types:

  1. Syntax Error: Syntax errors occur when the rules of Java syntax are violated. These errors are detected by the compiler during the compilation process. Common syntax errors include misspelled keywords, missing semicolons, and incorrect use of operators. Syntax errors prevent the program from being compiled successfully.
  2. Runtime Error: Runtime errors, also known as exceptions, occur during the execution of a program. These errors occur when unexpected conditions or situations arise while the program is running. Common examples include dividing by zero, accessing an array element out of bounds, and attempting to use a null object reference. Runtime errors cause the program to terminate abruptly unless they are handled using exception handling mechanisms such as try-catch blocks.
  3. Logical Error: Logical errors occur when the program does not produce the expected output due to incorrect logic or algorithmic errors in the code. Unlike syntax errors and runtime errors, logical errors do not cause the program to terminate or produce error messages. Instead, they result in incorrect behavior or output. Debugging logical errors often involves careful analysis of the code’s logic and algorithm to identify and fix the underlying issue.

Escape Sequences and Comments

Comments

In Java, comments are non-executable statements that are ignored by the compiler. They are used to provide explanations, documentation, and annotations within the code. There are three types of comments in Java:

  1. Single-line comments: Single-line comments begin with two forward slashes (//). Everything after // on the same line is considered a comment and is ignored by the compiler. Single-line comments are typically used for short explanations or comments on a single line of code.
    Example:

    // This is a single-line comment
    
  2. Multi-line comments: Multi-line comments, also known as block comments, are enclosed between /* and */. Everything between these symbols, including newlines, is considered a comment. Multi-line comments are often used for longer explanations or comments that span multiple lines of code.
    Example:

    /* This is a
       multi-line comment */
    
  3. Javadoc comments: Javadoc comments are a special type of comment used to generate documentation. They start with /** and end with */. Javadoc comments are used to describe classes, methods, and fields, and can include special tags to provide additional information such as parameters, return values, and exceptions.
    Example:

    /**
     * This is a Javadoc comment for the MyClass class.
     */
    public class MyClass {
        /**
         * This is a Javadoc comment for the myMethod method.
         * @param x This is a parameter of the method.
         * @return This method returns a value.
         */
        public int myMethod(int x) {
            return x * x;
        }
    }
    

Escape Sequences:

In Java, escape sequences are special character combinations used to represent characters that are difficult or impossible to represent directly in a string literal. Escape sequences are preceded by a backslash () character. Here are some common escape sequences used in Java:

  1. \n: Represents a newline character. When used within a string literal, it moves the cursor to the beginning of the next line.
  2. \t: Represents a tab character. When used within a string literal, it inserts a horizontal tab.
  3. \’: Represents a single quote character. Used to include single quote within a string literal.
  4. \”: Represents a double quote character. Used to include double quotes within a string literal.
  5. \\: Represents a backslash character. Used to include a backslash within a string literal.
  6. \r: Represents a carriage return character.
  7. \b: Represents a backspace character.
  8. \f: Represents a form feed character.

Example:

public class EscapeSequencesExample {
    public static void main(String[] args) {
        // Newline (\n) escape sequence
        System.out.println("Hello\nWorld"); // Output: Hello
                                            //         World
        
        // Tab (\t) escape sequence
        System.out.println("Java\tProgramming"); // Output: Java    Programming
        
        // Double quote (\") escape sequence
        System.out.println("She said, \"Hello!\""); // Output: She said, "Hello!"
        
        // Backslash (\\) escape sequence
        System.out.println("C:\\Users\\John\\Documents"); // Output: C:\Users\John\Documents
        
        // Carriage return (\r) escape sequence
        System.out.println("Overwritten text\r123"); // Output: 123written text
        
        // Backspace (\b) escape sequence
        System.out.println("Back\bspace"); // Output: Backspace
        
        // Form feed (\f) escape sequence
        System.out.println("Hello\fWorld"); // Output: Hello
                                             //         World

    }
}

 

Data Types

Naming Variables

In Java, variable names must adhere to certain standard rules to ensure clarity, readability, and compatibility with the language syntax. Here are the standard rules for naming variables in Java:

  1. Variable Name Length: Variable names can be of any length. However, it’s recommended to use meaningful and descriptive names while keeping them concise and readable.
  2. Valid Characters: Variable names can consist of letters (both uppercase and lowercase), digits, the underscore character (_), and the dollar sign ($). They must start with a letter, underscore, or dollar sign.
  3. Reserved Words: Variable names cannot be the same as Java keywords or reserved words. For example, you cannot name a variable “class” or “int” as they are reserved words in Java.
  4. Case Sensitivity: Java is case-sensitive, meaning uppercase and lowercase letters are treated as different characters. Therefore, “myVar” and “myvar” would be considered as two different variables.
  5. CamelCase Convention: It’s a common convention in Java to use CamelCase for naming variables. CamelCase involves writing compound words or phrases such that each word or abbreviation begins with a capital letter, with no spaces or punctuation between them. For example: myVariableName, totalAmount, studentAge.
  6. Meaningful Names: Variable names should be descriptive and convey the purpose or meaning of the variable. Avoid using single-letter variable names (except for loop counters) or overly cryptic abbreviations.
  7. Start with Lowercase: It’s a convention in Java to start variable names with a lowercase letter, except for constants, which are typically written in all uppercase.
  8. Special Characters: In addition to letters, digits, and underscore, you can use the dollar sign ($) as a special character in variable names. Avoid using other special characters like @, %, etc.

By adhering to these standard rules, you can create clear, concise, and meaningful variable names in Java code, promoting readability and maintainability.

Data Types

In Java, data types specify the type of data that can be stored in a variable. Java has two categories of data types: primitive data types and reference data types.

Primitive Data Types:

Primitive data types are the most basic data types in Java. They represent single values and are predefined by the language. There are eight primitive data types in Java:

  1. byte: Byte data type is an 8-bit signed two’s complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
  2. short: Short data type is a 16-bit signed two’s complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive).
  3. int: Int data type is a 32-bit signed two’s complement integer. It has a minimum value of -2^31 and a maximum value of 2^31-1.
  4. long: Long data type is a 64-bit signed two’s complement integer. It has a minimum value of -2^63 and a maximum value of 2^63-1.
  5. float: Float data type is a single-precision 32-bit IEEE 754 floating-point. It should never be used for precise values, such as currency.
  6. double: Double data type is a double-precision 64-bit IEEE 754 floating-point. It is used for decimal values that require more precision.
  7. boolean: Boolean data type represents one bit of information. It has only two possible values: true and false.
  8. char: Char data type is a single 16-bit Unicode character. It has a minimum value of ‘\u0000’ (0) and a maximum value of ‘\uffff’ (65,535 inclusive).

Example:

byte age = 25;
short distance = 10000;
int population = 1500000;
long nationalDebt = 20202020202020L; // Use 'L' suffix for long literals
float temperature = 32.5f; // Use 'f' suffix for float literals
double pi = 3.14159265359;
boolean isJavaFun = true;
char grade = 'A';

These primitive data types are the building blocks of Java programs, allowing developers to store and manipulate different types of data efficiently. Understanding their characteristics and appropriate usage is essential for writing effective Java code.

Note: There is srt which refers to string, but it is considered as an object data type.

Introduction

Object-oriented programming

Object-oriented programming is a methodology or paradigm to design a program using classes and objects. It has many advantages like:

  • Reusability.
  • Readability.
  • Performance.
  • Space.

Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects. Java is a powerful and widely-used programming language that fully supports OOP principles.

Other languages that support OOP: Python, C++, Visual Basic, NET and Ruby.

There are other methodologies like:

  • Procedural programming that is used by C, Pascal, COBOL, FORTRAN, Java, Python, C++ ..etc.
  • Event-driven that is used by C#, Visual Basic, Visual C++ and Java.

Objects are fundamental building blocks in object-oriented programming (OOP) and play a crucial role in the design and implementation of systems. To illustrate this concept, let’s consider the example of designing a store system.

When we think about building a store system, the first thing that comes to mind is the objects involved. In this case, we can identify three main objects: products, customers, and payment methods.

Products: Products represent the items that the store sells. These could be anything from groceries to electronics or clothing. Each product in the store is characterized by its unique attributes such as name, price, quantity, and category. In OOP, products can be represented as objects with properties and behaviors. For example, we could have a Product class with attributes like name, price, and quantity, and methods to update product information or check availability.

Customers: Customers are individuals or entities who visit the store to purchase products. They interact with the store by browsing products, selecting items for purchase, and completing transactions. In OOP, customers can be modeled as objects with attributes such as name, address, contact information, and purchase history. We could have a Customer class with methods to place orders, view order history, or update personal details.

Payment Method: Payment methods are mechanisms used by customers to pay for their purchases. These could include cash, credit/debit cards, mobile wallets, or online payment gateways. Each payment method has its own set of rules and procedures for processing transactions. In OOP, payment methods can be represented as objects with properties and behaviors related to processing payments. We could define different payment method classes with methods to authorize payments, handle refunds, or generate transaction receipts.

By identifying these objects and their relationships, we can design a cohesive and modular store system that encapsulates the functionality of managing products, serving customers, and processing payments. Each object in the system encapsulates its own state and behavior, promoting encapsulation, modularity, and code reuse, which are key principles of object-oriented programming.

Objects

Objects in object-oriented programming (OOP) are composed of two essential members: data (properties, attributes) and operations (methods, functions, behaviors). These elements encapsulate the state and behavior of the object, respectively, and work together to represent real-world entities within a software system.

Let’s explore the car example to better understand these concepts:

  1. Attributes:
    Name: Represents the brand or manufacturer of the car.
    Max Speed: Indicates the maximum speed the car can achieve.
    Price: Denotes the cost or price of the car.
    Model: Represents the specific model or version of the car.
  2. Operations:
    move(): Represents the action of moving the car. This method may involve starting the engine, accelerating, braking, and steering.
    calculateVehicleAge(): Calculates the age of the car based on its manufacturing year or model year.
  3. Getters and Setters:
    get(): Getter methods retrieve the current value of an attribute.
    set(): Setter methods modify or update the value of an attribute.

For example, in the car class, we may have getter and setter methods for each attribute, such as getName() and setName() for the name attribute, getMaxSpeed() and setMaxSpeed() for the max speed attribute, and so on. These methods allow external code to access and modify the state of the car object in a controlled manner, promoting encapsulation and data integrity.

Additionally, the class diagram is a graphical representation of the structure and relationships of classes in a software system. It visually depicts the classes, their attributes, methods, and associations with other classes. Class diagrams provide a high-level overview of the system’s architecture and help developers understand the relationships between different components.

Classes

In object-oriented programming (OOP), a class is a blueprint or template that defines the structure and behavior of objects. It serves as a blueprint for creating objects with similar characteristics and functionalities. Classes encapsulate data (attributes) and operations (methods) into a single unit, providing a modular and reusable way to model real-world entities within a software system.

 

Classes and Objects

Creating a Class in Java using NetBeans:

Classes are like blueprints that define the structure and behavior of objects in Java. Think of them as templates for building specific objects with unique properties and abilities.

In Apache NetBeans, follow these steps to create a new class:

Project Setup:

  1. Go to File > New Project > Java Application.
  2. Name your project (e.g., JavaOOP) and click Finish.

Package Creation:

  1. Navigate to the Source Packages section.
  2. Click the + sign and choose New > Java Package.
  3. Name your package (e.g., com.mycompany.javaoop) and click Finish.

Class Creation:

  1. Right-click on the package you created.
  2. Select New > Java Class.
  3. Name your class (e.g., Main) and click Finish.

Code:

package com.mycompany.javaoop;

public class Main {
    public static void main(String[] args) {
        System.out.println("JAVA");
    }
}

Explanation of the Code:

– package com.mycompany.javaoop;: This line specifies the package where your Main class belongs. Organizing classes into packages helps maintain code structure and avoid naming conflicts.
– public class Main: This declares a public class named Main. Public classes can be accessed from other parts of your project.
– public static void main(String[] args): This is the main method, the entry point where your program execution begins.
– System.out.println(“JAVA”);: This line prints the string “JAVA” to the console.

Troubleshooting and Tips:

<No main classes found> Error: If you encounter this error, ensure you’ve set the Main Class field in your project’s Run configuration to com.mycompany.javaoop.Main.

Here’s how to address the “No main classes found” error in NetBeans:

  1. Right-click on the project name (in this case, “JavaOOP”) in the Projects window.
  2. Select Properties.
  3. Go to the Run category.
  4. In the Main Class field, enter the fully qualified name of your main class, including the package name. For example, if your class is named “Main” and it’s in the package “com.mycompany.javaoop”, you would enter com.mycompany.javaoop.Main.
  5. Click OK to save the changes.

Now try running your code again. It should execute without the “No main classes found” error.

Creating Classes and Objects:

Separate Files for Separate Classes: Each class in Java needs its own file, distinct from the Main class. This promotes organization and modularity in your code.

Creating the Car Class:

  1. Right-click on the package where you want to create the new class (e.g., com.mycompany.javaoop).
  2. Select New > Java Class.
  3. Name the class Car (capitalizing the first letter is a Java naming convention).
  4. Click Finish. This generates a new file named Car.java within your package.

Naming Convention for Classes:

  • Always start class names with a capital letter.
  • Use descriptive names that reflect the class’s purpose (e.g., Car, Person, Account).
  • This convention makes your code more readable and easier to understand.

Example 1:

class Car {
    String name;
    int maxSpeed;
    float price;
    int model;
}

Class Declaration:

  • class Car – This line declares a new class named Car.

Attributes:

  • String name; – This defines an attribute named name of type String. It will store the name of the car object.
  • int maxSpeed; – This defines an attribute named maxSpeed of type int. It will store the maximum speed of the car object in kilometers per hour.
  • float price; – This defines an attribute named price of type float. It will store the price of the car object in a floating-point format.
  • int model; – This defines an attribute named model of type int. It will store the model year of the car object.

Now we will create our instances for Car class in the Main class, because it is the entry point of the program where execution starts.

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.maxSpeed = 210;
        Car c2 = new Car();
        c2.name = "Kia";
        System.out.println(c1.name);
        System.out.println(c1.maxSpeed);
        System.out.println(c2.name);
    }
}

This code still uses the Car class with attributes like name, maxSpeed, price, and model.
Main Class:

  • public static void main(String args[]): This line remains the entry point of your program.
  • Car c1 = new Car();: This line creates a new instance of the Car class and assigns it to the variable c1.
  • c1.name = “Tesla”;: This line sets the name attribute of the c1 object to “Tesla”.
  • c1.maxSpeed = 210;: This line sets the maxSpeed attribute of the c1 object to 210 kilometers per hour.
  • Car c2 = new Car();: This line creates another new instance of the Car class and assigns it to the variable c2.
  • c2.name = “Kia”;: This line sets the name attribute of the c2 object to “Kia”.
  • System.out.println(c1.name);: This line prints the value of the name attribute of the c1 object to the console, which should output “Tesla”.
  • System.out.println(c1.maxSpeed);: This line prints the value of the maxSpeed attribute of the c1 object to the console, which should output “210”.
  • System.out.println(c2.name);: This line prints the value of the name attribute of the c2 object to the console, which should output “Kia”.

Example 2:

Car Class:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) {
        name = n;
    }
    String getName() {
        return name;
    }
}
  • It has four attributes: name, maxSpeed, price, and model. These attributes are not shown in this example, but they could store information about a car’s name, maximum speed, price, and model year.
  • It also has two methods:
    – setName(String n): This method takes a string argument n and sets the car’s name attribute to that value.
    – getName(): This method returns the current value of the car’s name attribute as a string.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setName("KIA");
        System.out.println(c1.getName());
    }
}
  • It creates a new instance of the Car class and assigns it to the variable c1.
  • It sets the car’s name attribute to “Tesla” using the direct assignment (c1.name = “Tesla”).
  • Then, it overwrites the name by calling the setName method with the argument “KIA”. This method changes the internal name attribute of the c1 object.
  • Finally, it prints the car’s name using the getName method, which retrieves the current value (“KIA”) and prints it to the console.

Example 3:

Class Car:

class Car { 
    String name; 
    int maxSpeed; 
    float price; 
    int model;
    
    void setName(String n) { // Setters/ Mutators
        name = n;
    }
    String getName() {       // Getters/ Accessors
        return name;
    }
    void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    int getModel() {
        return model;
    }
}
  • Attributes: It still has name, maxSpeed, price, and model.
  • Methods:
    – Setters: These methods allow setting specific attribute values.
    – setName(String n): Sets the name attribute.
    – setModel(int m): Sets the model attribute with a validation check, only accepting years 2015 or later.
    – Getters: These methods retrieve specific attribute values.
    – getName(): Returns the name attribute value.
    – getModel(): Returns the model attribute value.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
        c1.name = "Tesla";
        c1.setModel(2021);
        System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object.
  • c1.name = “Tesla”;: Sets the name attribute of c1 using the default behavior (no setter needed).
  • c1.setModel(2021);: Sets the model attribute of c1 using the setter. Since 2021 is valid, it updates the model.
  • System.out.println(c1.getModel());: Prints the model attribute of c1, which should output “2021”.

Access Level Modifiers in Java

(Controlling Visibility and Encapsulation)

Access level modifiers are fundamental constructs in Java that determine the visibility and accessibility of class members (fields, methods, constructors). They play a crucial role in promoting encapsulation, a core principle of object-oriented programming that ensures data protection and modularity.

Key Concepts:

  • Visibility: Refers to whether a class member is directly visible and usable from other parts of your code.
  • Accessibility: Refers to the ability to directly access a class member without using special mechanisms.

Types of Access Level Modifiers:

  1. Public:
    Members declared public are visible and accessible from anywhere in your program.
    Use this modifier judiciously for elements that need to be widely used, but be cautious not to expose implementation details unnecessarily.
  2. Private:
    Members declared private are only visible and accessible within the class where they are defined.
    This promotes encapsulation by restricting direct access to internal data, encouraging the use of public methods to control interactions with the class.
  3. Protected:
    Members declared protected are visible and accessible within the class where they are defined, its subclasses in the same package, and subclasses in different packages (but not directly from other classes in different packages).
    This modifier is useful for creating a base class (superclass) with protected members that can be accessed and potentially overridden by its subclasses, promoting code reuse and inheritance.
  4. Default (Package-Private):
    Members declared without any access modifier are visible and accessible within the same package (the package containing the class definition).
    This provides a balance between visibility and access control within a package.

Example 4:

This code effectively demonstrates fundamental object-oriented concepts like encapsulation, access modifiers, and object interaction in Java. It provides a solid foundation for building more complex and robust Java applications.

Car Class:

public class Car { 
    private String name; 
    private int maxSpeed; 
    private float price; 
    private int model;
    
    public void setName(String n) { // Setters/ Mutators
        name = n;
    }
    public String getName() {       // Getters/ Accessors
        return name;
    }
    public void setModel(int m) {
        if(m >= 2015)
            model = m;
        else
            System.out.println("Sorry, we do not accept this model");
    }
    public int getModel() {
        return model;
    }
}
  • Attributes:
    – name: Private String storing the car’s name.
    – maxSpeed: Private int storing the car’s maximum speed.
    – price: Private float storing the car’s price.
    – model: Private int storing the car’s model year.
  • Methods:
    – setName(String n): Public setter to set the car’s name.
    – getName(): Public getter to retrieve the car’s name.
    – setModel(int m): Public setter to set the car’s model year, including validation for years 2015 or later.
    – getModel(): Public getter to retrieve the car’s model year.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Car c1 = new Car();
    c1.setModel(2021);
    System.out.println(c1.getModel()); // 2021
    }
}
  • Car c1 = new Car();: Creates a new Car object named c1.
  • c1.setModel(2021);: Attempts to set the model of c1 to 2021. This succeeds because 2021 is a valid year.
  • System.out.println(c1.getModel());: Prints the model of c1 to the console, which outputs “2021”.

Key Points:

  • Encapsulation: The Car class encapsulates its data using private attributes, ensuring controlled access through public methods.
  • Data Validation: The setModel method includes validation to prevent invalid model years, promoting data integrity.
  • Object Interaction: The Main class demonstrates how to create a Car object and interact with it using its public methods.
  • Setters and Getters: These methods provide a controlled way to modify and retrieve object attributes, upholding encapsulation principles.

Data Hiding

Data Hiding is a software development technique specifically used in object-oriented programming (OOP). Data hiding ensures exclusive data access to class members and protects object integrity by preventing unintended or intended changes.

Why do we use this technique?
Because we could have many object that will connect through messages and use each other methods.

Encapsulation
Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.

To achieve encapsulation in Java:

  • Declare the variables of a class as private.
  • Provide public setter and getter methods to modify and view the variables values.

Questions and Exercises

Build a class to find the area and circumference of a circle

Circle class:

package com.mycompany.javaoop;

public class Circle {
    private double radius;
    private String color;
    
    public double getRadius() {
        return radius;
    }
    
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public double getArea() {
        return Math.PI * radius * radius;
    }
    
    public double getCircumference() {
        return Math.PI * 2 * radius;
    }
    
    public String toString() {
        return "Circle{" + "radius=" + radius + ", color=" + color + "}";
    }
}

Attributes:

  • radius: Private double attribute to store the circle’s radius.
  • color: Private String attribute to store the circle’s color (optional, for additional information).

Methods:

– Getters and Setters:

  • getRadius(): Returns the current value of the radius attribute.
  • setRadius(double radius): Sets the value of the radius attribute, potentially with validation (not included in this example).
  • getColor(): Returns the current value of the color attribute (if present).
  • setColor(String color): Sets the value of the color attribute (if present).

– Area and Circumference:

  • getArea(): Calculates and returns the area of the circle using Math.PI * radius * radius.
  • getCircumference(): Calculates and returns the circumference of the circle using Math.PI * 2 * radius.
  • toString(): Overrides the default toString() method to provide a more descriptive representation of the Circle object, including its radius and color (if present).

Main Class:

package com.mycompany.javaoop;

public class Main
{
    public static void main(String args[]) {
        Circle c1 = new Circle(), c2 = new Circle();
        c1.setRadius(3.0);
        c1.setColor("Black");
        System.out.println("c1 area = " + c1.getArea());
        System.out.println(c1.toString());
        
        c2.setRadius(2.0);
        c2.setColor("Blaue");
        System.out.println("c2 Circumference = " + c2.getCircumference());
    }
}
  • Creates two Circle objects: c1 and c2.
  • Sets the radius and color (if applicable) for each object.
  • Calculates and prints the area of c1 and the circumference of c2.
  • Optionally, you could call c1.toString() and c2.toString() to print their complete representations.

Build a simple banking system

Account class:

package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}package com.mycompany.javaoop;

public class Account {
    private int accountNo;
    private String name;
    private float amount;
    
    public void insert(int a, String n, float amt) {
        this.accountNo = a;
        this.name = n;
        this.amount = amt;
    }
    
    public void deposit(float amt) {
        this.amount = this.amount + amt;
        System.out.println(amt + "deposited");
    }
    
    public void withdraw(float amt) {
        if(amount < amt) {
            System.out.println("Insufficient Balance")
        } else {
            this.amount = this.amount - amt;
            System.out.println(amt + "withdrawn");
        }
    }
    
    public void checkBalance() {
        System.out.println("Balance = " + this.amount);
    }
    
    public String toString() {
        return "Account{" + "accountNo=" + accountNo + ", name =" + name + ", amount=" + amount; 
    }
}

Attributes:

  • accountNo: Private int stores the account number.
  • name: Private String stores the account holder’s name.
  • amount: Private float stores the account balance.

Methods:

  • insert(int a, String n, float amt):
    Initializes an account with the provided account number, name, and initial amount.
  • deposit(float amt):
    Deposits the specified amount into the account.
    Prints a confirmation message with the deposited amount.
  • withdraw(float amt):
    Withdraws the specified amount from the account, but only if there’s sufficient balance.
    Prints a confirmation message if successful, or an “Insufficient Balance” message otherwise.
  • checkBalance():
    Displays the current account balance.
  • toString():
    Overrides the default toString() method to provide a custom string representation of the account, including its account number, name, and balance.

Now complete this code as an exercise by creating the appropriate instances. For further information please watch this video: Questions and Exercises – Classes and Objects

Constructor (No-Arg, Parameterized, Default)

What is a Constructor?

  • It’s a special method in a Java class that’s automatically invoked when a new object of that class is created.
  • Its primary purpose is to initialize the object’s attributes (fields or variables) to appropriate initial values.
  • It ensures objects are created in a valid and consistent state.

Rules for Creating Constructors:

  1. Same Name as Class: The constructor’s name must be exactly the same as the class name.
  2. No Explicit Return Type: Constructors don’t have a return type, not even void.
  3. Cannot Have Modifiers: Constructors cannot be declared as abstract, static, final, or synchronized.

Constructor Types:

  1. No-Arg Constructor: a constructor that does not accept any arguments.
    public class Product {
        private String name;
        private String description;
        private float price;
        private int quantity;
        private float discount;
    
        public Product() {
            this.name = "No name";
            this.description = "No description";
            this.price = 0.0f;
            this.quantity = 0;
            this.discount = 0;
        }
    }
  2. Parameterized Constructor: a constructor that accepts arguments.
    public Product(String n, String d, float p, int q, float dis) {
            this.name = n;
            this.description = d;
            this.price = p;
            this.quantity = q;
            this.discount = dis;
        }
  3. Default Constructor: A constructor that is automatically created by Java compiler if it is not explicitly defined.

Constructor Chaining

Constructor Chaining: When a constructor calls another constructor of the same class then it is called constructor chaining.

Code:

Product class:

public class Product {
    private String name;
    private String description;
    private float price;
    private int quantity;
    private float discount;
    private String color;
    
    public Product() {
        this.name = "No name";
        this.description = "No description";
        this.price = 0.0f;
        this.quantity = 0;
        this.discount = 0;
    }
    
    public Product(String n, String d, float p, int q, float dis) {
        this.name = n;
        this.description = d;
        this.price = p;
        this.quantity = q;
        this.discount = dis;
        System.out.println("constructor: 5");
    }
    
    public Product(String n, String d, float p, int q, float dis, String c) {
        this (n,d,p,q,dis);
        this.color = c;
        System.out.println("constructor: 6");
    }
    
    public void display() {
        System.out.println("Name = " + name);
        System.out.println("description = " + description);
        System.out.println("Price = " + price);
        System.out.println("Quantity = " + quantity);
        System.out.println("Discount = " + Discount);
    }
}

Attributes:

  • name: String representing the product name.
  • description: String describing the product.
  • price: float storing the product price.
  • quantity: int representing the product quantity.
  • discount: float representing the discount percentage.
  • color: String (optional) for the product color (added in the third constructor).

Constructors:

  • Product() (Default Constructor): Initializes all attributes with default values (“No name”, “No description”, etc.).
  • Product(String n, String d, float p, int q, float dis): Parameterized constructor taking arguments for name, description, price, quantity, and discount. Prints “constructor: 5” upon invocation.
  • Product(String n, String d, float p, int q, float dis, String c): Parameterized constructor taking arguments for all attributes, including color. Internally calls the second constructor (“constructor: 5”) and then sets the color. Prints “constructor: 6” upon invocation.
  • display() method: Prints the product information in a user-friendly format.

Main Class:

public class Main
{
    public static void main(String args[]) {
        Product p1 = new Product("Camera", "Auto focus", 99, 10, 5, "red");
        Product p2 = new Product();
        p.display();

    }
}

Creates two Product objects:

  • p1 using the third constructor, providing values for all attributes.
  • p2 using the default constructor (no arguments provided).

Attempts to call the display() method on the incorrectly referenced variable p (should be p2) to display the default values.

English