Lesson # 9. Classes

Theory

  • Classes are an expanded concept of data structures: like data structures, they can contain data members, but they can also contain functions as members.
  • An object is an instantiation of a class. In terms of variables, a class would be the type, and an object would be the variable.
  • Classes are defined using either keyword class or keyword struct, with the following syntax:
  • class class_name {
      access_specifier_1:
        member1;
      access_specifier_2:
        member2;
      ...
    } object_names;
    

    Where class_name is a valid identifier for the class, object_names is an optional list of names for objects of this class. The body of the declaration can contain members, which can either be data or function declarations, and optionally access specifiers.

  • C++ classes encapsulate data and associated functionality into an object:
  • // C++ class: 
    class Cube {
     public:
      double getVolume();
       // ...
     private:
      double length_;
    };
  • Thus, Classes have the same format as plain data structures, except that they can also include functions and have these new things called access specifiers. An access specifier is one of the following three keywords: private, public or protected. These specifiers modify the access rights for the members that follow them.
  • Encapsulation encloses data and functionality into a single unit (called a class)
  • In C++, data and functionality are separated into two separate protections: public and private.
  • The protection level determines the access that «client code» has to the member data or functionality:

  • Public members can be accessed by client code. So, public members are accessible from anywhere where the object is visible. protected members are accessible from other members of the same class (or from their «friends»), but also from members of their derived classes.
  • Private members cannot be accessed by client code (only used within the class itself). So, private members of a class are accessible only from within other members of the same class (or from their «friends»).
  • Example of header-file code (Cube.h):

    #pragma once
    class Cube {
     public:
       double getVolume();
       double getSurfaceArea();
       void setLength(double length);
     private:
       double length_;
    };

    Example of implementation-file code (Cube.cpp):

    #include "Cube.h"
    double Cube::getVolume() {
      return length_ * length_ * length_;
    }
    double Cube::getSurfaceArea() {
       return 6 * length_ * length_;
    }
    void Cube::setLength (double length) {
      length_ = length;
    }

    Example of main-file code (main.cpp):

    #include "Cube.h"
    int main() {
     Cube c;
     c.setLength(3.48);
     double volume = c.getVolume();
     std::cout << "Volume: " << volume << std::endl;
     return 0;
    }

    Arguments passed by …

      Identical to storage, arguments can be passed to functions in three different ways:

    • Pass by value (default)
    • Pass by pointer (modified with *)
    • Pass by reference (modified with &, acts as an alias)

    Values returned by …

    Similarly, values can be returned all three ways as well:

  • Return by value (default)
  • Return by pointer (modified with *)
  • Return by reference (modified with &, acts as an alias)
  • Class destructor

    • When an instance of a class is cleaned up, the class destructor is the last call in a class’s lifecycle.
    • An automatic default destructor is added to your class if no other destructor is defined.
    • The only action of the automatic default destructor is to call the default destructor of all member objects.
    • An destructor should never be called directly. Instead, it is automatically called when the object’s memory is being reclaimed by the system:
    • If the object is on the stack, when the function returns
    • If the object is on the heap, when delete is used
    • To add custom behavior to the end-of-life of the function, a custom destructor can be defined as:
    • A custom destructor is a member function.
    • The function’s destructor is the name of the class, preceded by a tilde ~.
    • All destructors have zero arguments and no return type.
    • Cube::~Cube(); // Custom destructor

    Labs and tasks

    Lab 1:
    To do: Create a Rectangle class and an object (i.e., a variable) of this class, called rect.
    1) The class should contain four members:
    — two data members of type int (member width and member height) with private access,
    — and two member functions with public access: the functions set_values and area.

    2) Define two member functions: set_values function should set the variables width and height to the values; are function should return width*height.

    3) Create a Custom default constructor to have the initial values for width and height (set them to 5).

    4) Set the width and height values for the rect object and print out the information about this object.

    Expected output:

    Lab 1:
    please, enter width:
    >> 20
    please, enter height:
    >> 2
    rect area: 40
    

    ✍ Algorithm:

    • To do the lab create empty console application with a name Lesson9. Add files: mainLab1.cpp, ImpLab1.cpp, HeaderLab1.h.
    • Include all the needed libraries and files.
    • 1.Create a Rectangle class:

    • The class must be defined inside a header file. So, open the header file and add the code to define the class with two private data members, they are width and height; and two member functions with public access, they are set_values and area.
    • class Rectangle {
      private:
      	int width, height;
      public:
      	void set_values(int, int);
      	int area(void);
      } ;
    • Here Rectangle is the class name (i.e., the type).
    • The functions set_values and area have a public access, it means that they can be accessed from inside the main function by simply inserting a dot (.) between object name and member name (e.g. rect.set_values…).
    • width and height members cannot be accessed from outside the class, since they have private access and they can only be referred to from within other members of that same class.
    • 2. Define two member functions:

    • Since members width and height have private access, access to them from outside the class is not allowed. So, we should define a member function to set values for those members within the object: the member function set_values.
    • Let’s create the definition of set_values member function. We’re going to have a member of a class outside the class itself, so, we have to use scope operator (::, two colons). You should create the definition of the function inside the implementation file:
    • void Rectangle::set_values(int x, int y) {
      	width = x;
      	height = y;
      }
      The scope operator (::) specifies the class to which the member being defined belongs, granting exactly the same scope properties as if this function definition was directly included within the class definition. For example, the function set_values has access to the variables width and height, which are private members of class Rectangle, and thus only accessible from other members of the class, such as this.
    • The second member function, that is area function, we’re going to have inside the class itself, just to try different ways of definition. So, return to the header file and add the definition inside the class next to int area(void) statement:
    • int area() {return width*height;}
      The function is automatically considered an inline member function by the compiler.

      3) Create a Custom default constructor to have the initial values for width and height (set them to 5).

    • Add the declaration of a Custom default constructor inside the public access of the class (header file):
    • public: // you had this code
      	Rectangle(); 
      	void set_values(int, int); // you had this code
      //...
    • Open your implementation file to add the definition of that constructor:
    •  Rectangle::Rectangle() {
      	width = 5;
      	height = 5;
      }

      4) Set the width and height values for the rect object and print out the information about this object:

    • Open a main file in the editor window. You should create an object (i.e., a variable) of the Rectangle class, called rect. And after this, ask user to input the width and height values. Call the set_values function and output the result:
    • int main() {
      	Rectangle rect;
      	int w, h;
      	cout << "please, enter width:\n";
      	cin >> w;
      	cout << "please, enter height:\n";
      	cin >> h;
      	rect.set_values(w, h);
      	cout << "rect area: " << rect.area() << endl;
      	system("pause");
      	return 0;
      }
    • Run the program and check the output.
    Task 1:

    To do: Create a LessonDate class to output the date of a lesson.

    1) The class should contain the following members:
    — three data members of type int with private access, they are day, month and year;
    — and two member functions with public access:
    void setDate(int, int, int); to set the date for the next lesson and
    void getDate(); to print out the date of the lesson.

    2) Create a three argument constructor to have the initial values for date; in the constructor body call the setDate function to set the date.

    3) Inside the main function create an object (i.e., a variable) of this class, called objLesson. Set the values of three parameters — day, month and year. Print out the information about this object.

    Expected output:

    Task 1:
    Lesson date: 11.11.2021
    Please, enter day, then month and year of the next lesson
    28
    12
    2020
    Lesson date: 28.12.2020
    

    [Solution and Project name: Lesson_9task1, file name L9Task1main.cpp, L9Task1imp.cpp, L9Task1.h]

    Lab 2:
    To do: Create a Cube class.
    1) The class should contain four members:
    length_ data member of type double with private access,
    — three member functions with public access: the functions double getVolume(); , double getSurfaceArea(); and void setLength(double length);.

    2) Give the definitions (implementations) of those functions:
    getVolume() function have to calculate a volume of the cube: length_ * length_ * length_;
    getSurfaceArea() function have to calculate a Surface Area of the cube: 6 * length_ * length_;;
    setLength(double length) function have to set the value for the cube length.

    3) Create a Custom default constructor to have the initial values for length_ (set it to 1).

    4) Inside the main cpp file create double cube_on_stack() function to create an object (i.e., a variable) of this class and get volume of it. This object will be in a stack memory. Also, inside the main function create a new cube of length 10 which is going to be in heap memory. Set the values. Print out the information about those objects.

    5) Create a custom destructor to delete an information about the cube.

    Expected output:

    Lab 2:
    Volume of c cube:
    Destructor called for cube with length 2
    Volume of c cube in the heap memory: 27
    Destructor called for cube with length 3
    

    ✍ Algorithm:

    • To do the lab create an empty console application with a name Lesson9Lab2. Create new files: mainLab2.cpp, ImpLab2.cpp, HeaderLab2.h.
    • Include all the needed libraries and files.
    • 1.The class should contain four members:

    • The interface of the class must be inside a header file. So, open the header file and add the code to define the class with one private data member, it is length_ of a cube; and three member functions with public access, they are getVolume(), getSurfaceArea() and setLength(double length).
    • class Cube
      {
      public:
      	double getVolume();
      	double getSurfaceArea();
      	void setLength(double length);
      private:
      	double length_;
      };
    • Here Cube is the class name (i.e., the type.
    • The functions getVolume(), getSurfaceArea() and setLength(double length) have a public access, it means that they can be accessed from anywhere where the object is visible.
    • length_ member cannot be accessed from outside the class, since it has a private access and it can only be accesses from within the class itself.
    • 2. Give the definitions (implementations) of the functions:

    • Let’s create the definition of setLength member function. We’re going to have a member of a class outside the class itself, so, we have to use scope operator (::, two colons). You should create the definition of the function inside the implementation cpp file:
    • void Cube::setLength(double length) {
      	length_ = length;
      }
      The scope operator (::) specifies the class to which the member being defined belongs, granting exactly the same scope properties as if this function definition was directly included within the class definition. For example, the function setLength has access to the variable length_, which is a private member of the class Cube, and thus only accessible from other members of the class, such as this.
    • The second and th third member functions are getVolume and getSurfaceArea function, we’re going to have them inside the implementation file too:
    • double Cube::getVolume() {
      	return length_ * length_ * length_;
      }
      double Cube::getSurfaceArea() {
      	return 6 * length_ * length_;
      }
      The getVolume function will return the volume of that cube, for which this function will be called.
      The getSurfaceArea function will return the surface area of that cube, for which this function will be called.

      3) Create a custom default constructor to have the initial values for length_ (set it to 1).

    • Add the declaration of a custom default constructor inside the public access of the class (header file):
    • public: // you had this code
      	Cube(); 
              //...
    • Open your implementation file to add the definition of that constructor:
    • Cube::Cube() {
      	length_ = 1;
      }

      4) Inside the main cpp file create double cube_on_stack() function to create an object (i.e., a variable) of this class and get volume of it:

    • Open a main file in the editor window. Before the main function add the code to create cube_on_stack() which will create the object of Cube class and return the volume of this object:
    • double cube_on_stack() {
      	Cube c;
      	c.setLength(2);
      	return c.getVolume();
      }
      int main() {
       // ...
      }
    • Inside the main function ptint out the message and call that function:
    • int main() {
        cout << "Volume of first cube: " << endl;
        cube_on_stack();
      }

      Also, inside the main function create a new cube of length 10 which is going to be in heap memory. Set the values. Print out the information about those objects.

    • Then, inside the main function you should create a new cube of length 10 which is going to be in heap memory:
    •   Cube * pcube = new Cube;
        pcube->setLength(3);
        cout << "Volume of c cube in the heap memory: " << pcube->getVolume() << endl;
      To have an object to be stored in the heap memory you should use star (*) sign. Such objects or instances to the objects can be used together with arrow operator to access their members.

      5) Create a custom destructor to delete an information about the cube.

    • Open header file to declare a class destructor, which will be called to clean up the instance of the class. Add it right after the class constructor to the public protection level:
    • ~Cube();
    • Add the implementation for that destructor inside implementation file:
    • Cube::~Cube(){
      	cout << "Destroyed cube with length " << length_;
      }
    • Return to the main file and add the delete keyword to clean up the memory of the pcube object:
    • // ...
      delete pcube;
      If the object is on the heap, the destructor is only called when that delete keyword is used, to reclaim that memory that the object was using.
    • Run the program and check the output.
    Task 2:

    To do: Create a Student class to output information about the students.

    1) The class should contain the following members:
    — two data members of type string with private access, they are name and surname, and one data member of type intage;
    — and two member functions with public access:
    void set_info(string, string, int); to set the information about the student
    and void get_info(void); to print out the information.

    2) Create a three argument constructor to have the initial values for student.

    3) Inside the main cpp file create void student_on_stack() function to create an object (i.e., a variable) of this class and get volume of it. This object will be in a stack memory. Also, inside the main function create a new student with some info about, which is going to be in a heap memory. Print out the information about those objects.

    4) create a custom destructor to delete an information about student.

    Expected output:

    Task 2:
    info about student1: name: Johnsurname: Ivanovage: 20
    Destructor called for Student Ivanov
    info about student2: name: Petersurname: Panage: 17
    Destructor called for Student Pan
    

    [Solution and Project name: Lesson_9task2, file name L9Task2main.cpp, L9Task2imp.cpp, L9Task2.h]

    Task 3:

    To do: Create a BookShop class to store and output an information about the selling books.

    1) The class should contain the following members:
    data members with private access:
    title_ (a title of a book) of type string;
    author_ (an author of a book) of type string;
    _price (a price of a book) of type double;
    _discount (a discount for a price of a book) of type int.
    data members with public access:
    void getInfo() function to print out the information about the book;
    void set_info(string title, string author, double price, int discount) function to set the information about the book;
    double getTotalPrice() function calculate the price of a book considering the discount (price — (price * discount)).

    2) Create a four argument constructor to have the initial values for books.

    3) Create two objects and print out the information about those objects. Print out the info about the price considering the discount.

    Expected output:

    Task 3:
    // book 1 info:
    Dostoevsky Demons 205 roubles, discount 0.05, total price 194,75 roubles
    // book 2 info:
    Kuprin Duel 125 roubles, discount 0.1, total price 112,5 roubles
    

    [Solution and Project name: Lesson_9task3, file name L9Task3main.cpp, L9Task3imp.cpp, L9Task3.h]

Lesson # 10. Lists

Theory

Forward_list or singly-linked lists

  • Forward lists are sequence containers that allow constant time insert and erase operations anywhere within the sequence.
  • template < class T, class Alloc = allocator > class forward_list;

    T — Type of the elements.
    Aliased as member type forward_list::value_type.
    Alloc — Type of the allocator object used to define the storage allocation model. By default, the allocator class template is used, which defines the simplest memory allocation model and is value-independent. Aliased as member type forward_list::allocator_type.

  • Forward lists are implemented as singly-linked lists; Singly linked lists can store each of the elements they contain in different and unrelated storage locations. The ordering is kept by the association to each element of a link to the next element in the sequence.
  • Forward list keeps internally only a link to the next element.
  • Links lack direct access to the elements by their position; For example, to access the sixth element in a forward_list one has to iterate from the beginning to that position, which takes linear time in the distance between these. They also consume some extra memory to keep the linking information associated to each element
  • Sequence

  • Elements in sequence containers are ordered in a strict linear sequence. Individual elements are accessed by their position in this sequence.
  • Linked list

  • Each element keeps information on how to locate the next element, allowing constant time insert and erase operations after a specific element (even of entire ranges), but no direct random access.
  • Construct forward_list object
    // forward_list constructors
    #include <iostream>
    #include <forward_list>
     
    int main ()
    {
     
      std::forward_list<int> first;                      // (1) default: empty
      std::forward_list<int> second (3,77);              // (2) fill: 3 seventy-sevens
      std::forward_list<int> third (second.begin(), second.end()); // (3) range initialization
      std::forward_list<int> fourth (third);            // (4) copy constructor
      std::forward_list<int> fifth (std::move(fourth));  // (5) move ctor. (fourth wasted)
      std::forward_list<int> sixth = {3, 52, 25, 90};    // (6) initializer_list constructor
     
      std::cout << "first:" ; for (int& x: first)  std::cout << " " << x; std::cout << '\n';
      std::cout << "second:"; for (int& x: second) std::cout << " " << x; std::cout << '\n';
      std::cout << "third:";  for (int& x: third)  std::cout << " " << x; std::cout << '\n';
      std::cout << "fourth:"; for (int& x: fourth) std::cout << " " << x; std::cout << '\n';
      std::cout << "fifth:";  for (int& x: fifth)  std::cout << " " << x; std::cout << '\n';
      std::cout << "sixth:";  for (int& x: sixth)  std::cout << " " << x; std::cout << '\n';
     
      return 0;
    }

    Expected output:

    first:
    second: 77 77 77
    third: 77 77 77
    fourth:
    fifth: 77 77 77
    sixth: 3 52 25 90

    (1) — default — Constructs an empty container, with no elements.
    (2) — fill constructor — Constructs a container with n elements. Each element is a copy of val (if provided).
    (3) — range constructor — Constructs a container with as many elements as the range [first,last), with each element emplace-constructed from its corresponding element in that range, in the same order.
    (4) — copy constructor (and copying with allocator) — Constructs a container with a copy of each of the elements in fwdlst, in the same order.
    (5) — move constructor (and moving with allocator) — Constructs a container that acquires the elements of fwdlst. If alloc is specified and is different from fwdlst‘s allocator, the elements are moved. Otherwise, no elements are constructed (their ownership is directly transferred). fwdlst is left in an unspecified but valid state.
    (6) — initializer list constructor — Constructs a container with a copy of each of the elements in il, in the same order.

Forward_list::assign

Syntax:
range (1)

template 
void assign (InputIterator first, InputIterator last);

fill (2)

void assign (size_type n, const value_type& val);

initializer list (3)

void assign (initializer_list il);
  • In the range version (1), the new contents are elements constructed from each of the elements in the range between first and last, in the same order.
  • In the fill version (2), the new contents are n elements, each initialized to a copy of val.
  • In the initializer list version (3), the new contents are copies of the values passed as initializer list, in the same order.
  • Any elements held in the container before the call are destroyed and replaced by newly constructed elements (no assignments of elements take place).
    Parameters:
    first, last
    Input iterators to the initial and final positions in a sequence. The range used is [first,last), which includes all the elements between first and last, including the element pointed by first but not the element pointed by last.
    The function template argument InputIterator shall be an input iterator type that points to elements of a type from which value_type objects can be constructed.
    n
    New size for the container.
    Member type size_type is an unsigned integral type.
    val
    Value to fill the container with. Each of the n elements in the container will be initialized to a copy of this value.
    Member type value_type is the type of the elements in the container, defined in forward_list as an alias of its first template parameter (T).
    il
    An initializer_list object. The compiler will automatically construct such objects from initializer list declarators. Member type value_type is the type of the elements in the container, defined in forward_list as an alias of its first template parameter (T).
    Example:

    #include <iostream>
    #include <forward_list>
     
    int main ()
    {
      std::forward_list<int> first;
      std::forward_list<int> second;
     
      first.assign (4,15);                           // 15 15 15 15
     
      second.assign (first.begin(),first.end());     // 15 15 15 15
     
      first.assign ( {77, 2, 16} );                  // 77 2 16
     
      std::cout << "first contains: ";
      for (int& x : first) std::cout << ' ' << x;
      std::cout << '\n';
     
      std::cout << "second contains: ";
      for (int& x : second) std::cout << ' ' << x;
      std::cout << '\n';
     
      return 0;
    }

    Output:

    first contains: 77 2 16
    second contains: 15 15 15 15
    Assignment operator = with forward_list

    Syntax:
    copy (1)

    forward_list& operator= (const forward_list& fwdlst);

    move (2)

    forward_list& operator= (forward_list&& fwdlst);

    initializer list(3)

    forward_list& operator= (initializer_list il);

    Assigns new contents to the container, replacing its current contents.

  • The copy assignment (1) copies all the elements from fwdlst into the container (with fwdlst preserving its contents).
  • The move assignment (2) moves the elements of fwdlst into the container (x is left in an unspecified but valid state).
  • The initializer list assignment (3) copies the elements of il into the container.
  • The container preserves its current allocator, except if the allocator traits indicate fwdlst’s allocator should propagate. This allocator is used (through its traits) to allocate or deallocate if there are changes in storage requirements, and to construct or destroy elements, if needed.
    Parameters:
    fwdlst
    A forward_list object of the same type (i.e., with the same template parameters, T and Alloc).
    il
    An initializer_list object. The compiler will automatically construct such objects from initializer list declarators. Member type value_type is the type of the elements in the container, defined in forward_list as an alias of its first template parameter (T).
    Example:

    #include <iostream>
    #include <forward_list>
     
    template<class Container>
    Container by_two (const Container& x) {
      Container temp(x); 
      for (auto& x:temp) 
          x*=2;
      return temp;
    }
     
    int main ()
    {
      std::forward_list<int> first (4);      // 4 ints
      std::forward_list<int> second (3,5);   // 3 ints with value 5
     
      first = second;                        // copy assignment
      second = by_two(first);                // move assignment
     
      std::cout << "first: ";
      for (int& x : first) std::cout << ' ' << x;
      std::cout << '\n';
     
      std::cout << "second: ";
      for (int& x : second) std::cout << ' ' << x;
      std::cout << '\n';
     
      return 0;
    }

    In the first assignment, second is an lvalue: the copy assignment function is called.
    In the second assignment, the value returned by by_two(first) is an rvalue: the move assignment function is called.
    Output:

    first: 5 5 5
    second: 10 10 10
    resize () function
    void resize (size_type n);
    void resize (size_type n, const value_type& val);

    Resizes the container to contain n elements.
    If n is smaller than the current number of elements in the container, the content is trimmed to contain only its first n elements, removing those beyonf (and destroying them).
    If n is greater than the current number of elements in the container, the content is expanded by inserting at the end as many elements as needed to reach a size of n elements. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.
    Example

    // resizing forward_list
    #include <iostream>
    #include <forward_list>
     
    int main ()
    {
      std::forward_list<int> mylist = {10, 20, 30, 40, 50};
                                    // 10 20 30 40 50
      mylist.resize(3);             // 10 20 30
      mylist.resize(5,100);         // 10 20 30 100 100
     
      std::cout << "mylist contains:";
      for (int& x: mylist) std::cout << ' ' << x;
      std::cout << '\n';
     
      return 0;
    }
    mylist contains: 10 20 30 100 100
    insert_after function

    Example

    // forward_list::insert_after
    #include <iostream>
    #include <array>
    #include <forward_list>
     
    int main ()
    {
      std::array<int,3> myarray = { 11, 22, 33 };
      std::forward_list<int> mylist;
      std::forward_list<int>::iterator it;
     
      it = mylist.insert_after ( mylist.before_begin(), 10 );          // 10
                                                                       //  ^  <- it
      it = mylist.insert_after ( it, 2, 20 );                          // 10 20 20
                                                                       //        ^
      it = mylist.insert_after ( it, myarray.begin(), myarray.end() ); // 10 20 20 11 22 33
                                                                       //                 ^
      it = mylist.begin();                                             //  ^
      it = mylist.insert_after ( it, {1,2,3} );                        // 10 1 2 3 20 20 11 22 33
                                                                       //        ^
     
      std::cout << "mylist contains:";
      for (int& x: mylist) std::cout << ' ' << x;
      std::cout << '\n';
      return 0;
    }

    Output:

    mylist contains: 10 1 2 3 20 20 11 22 33

    Doubly linked lists

    • Lists are sequence containers that allow constant time insert and erase operations anywhere within the sequence, and iteration in both directions.
    • template < class T, class Alloc = allocator > class list;
    • List containers are implemented as doubly-linked lists.
    • Doubly linked lists can store each of the elements they contain in different and unrelated storage locations. The ordering is kept internally by the association to each element of a link to the element preceding it and a link to the element following it.
    • Doubly linked list keeps two links per element: one pointing to the next element and one to the preceding one, allowing efficient iteration in both directions, but consuming additional storage per element and with a slight higher time overhead inserting and removing elements.
    • Compared to other base standard sequence containers (array, vector and deque), forward_list perform generally better in inserting, extracting and moving elements in any position within the container, and therefore also in algorithms that make intensive use of these, like sorting algorithms.

    * Information has taken from: http://www.cplusplus.com/reference/forward_list/forward_list/.

    Labs and tasks

    Lesson # 8. Structures

    Theory

    Structures in C++

      Example:

      1
      2
      3
      4
      5
      6
      7
      
      struct product {
        int weight;
        double price;
      } ;
       
      product apple;
      product banana, melon;
      This declares a structure type, called product, and defines it having two members: weight and price, each of a different fundamental type. This declaration creates a new type (product), which is then used to declare three objects (variables) of this type: apple, banana, and melon. Note how once product is declared, it is used just like any other type.
    • Right at the end of the struct definition, and before the ending semicolon (;), the optional field object_names can be used to directly declare objects of the structure type. For example, the structure objects apple, banana, and melon can be declared at the moment the data structure type is defined:
    • 1
      2
      3
      4
      
      struct product {
        int weight;
        double price;
      } apple, banana, melon;
      In this case, where object_names are specified, the type name (product) becomes optional: struct requires either a type_name or at least one name in object_names, but not necessarily both.

    Access to the objects’ members

  • Once the three objects of a determined structure type are declared (apple, banana, and melon) its members can be accessed directly. The dot notation is used. Dot (.) must be inserted between the object name and the member name. For example, we could operate with any of these elements as if they were standard variables of their respective types:
  • 1
    2
    3
    4
    5
    6
    
    apple.weight
    apple.price
    banana.weight
    banana.price
    melon.weight
    melon.price
    Each one of these has the data type corresponding to the member they refer to: apple.weight, banana.weight, and melon.weight are of type int, while apple.price, banana.price, and melon.price are of type double.

    Pointers to structures

  • Structures can be pointed to by its own type of pointers:
  • 1
    2
    3
    4
    5
    6
    7
    
    struct Product_t {
      int weight;
      double price;
    } apple, banana, melon;
     
    Product_t aproduct;
    Product_t * pproduct;
    Here aproduct is an object of structure type Product_t, and pproduct is a pointer to point to objects of structure type Product_t.
  • Therefore, the following code would also be valid:
  •  
    pproduct = &aproduct;
    
    The value of the pointer pproduct would be assigned the address of object aproduct.
  • The following example serve to introduce a new operator: the arrow operator (->):
  • //...
    struct Product_t {
      int weight;
      double price;
    } ;
     
    int main ()
    {
      string mystr;
     
      Product_t aproduct;
      Product_t * pproduct;
      pproduct = &aproduct;
     
      cout << "Enter weight: ";
      cin >> pproduct ->weight;
      cout << "Enter price: ";
      cin >> pproduct ->price;
     
      cout << "\nYou have entered:\n";
      cout << pproduct ->weight << " ";
      cout << pproduct ->price;
     
      return 0;
    }

    Labs and tasks

    Lab 1:
    To do: Create a Books_t structure for storing data about the books. Add the following properties (members) of an object:

    • book’s title
    • year of work

    Tasks:

    1. Create a Books_t structure
    2. Implement a method for printing out the information about the objects:
    3. void printBook(Books_t book);
    4. Specify two object names (e.g. Pushkin, Chekhov).
    5. In the main program, create at least 2 objects, display summaries on those books.

    Expected output:

    Lab 1:
    Enter year of Chekhov work Three Sisters:
    1897
    Pushkin's work is:
     Eugene Onegin 1823
    And Chekhov's:
     Three Sisters 1897
    

    ✍ How to do:

    • To do the lab create empty console application with a name Lesson8. Add files: main8.cpp, structBooks8.cpp, structBooks8.h.
    • Include all the needed libraries and files.
    • 1. Create a structure Books_t for storing data about the books. Add the following properties (members) of an object: book’s title, year of work.

    • The structure must be defined inside a header file. So, open the structBooks8.h and add the code to define the structure with two members, they are title and year:
    • struct Books_t
      {
      	string title;
      	int year;
      };
      

      2. Implement a method for printing out the information about the objects.

    • Also inside the header file you should define the method with a parameter of Books_t type, to accept a particular book from the main program. Add the code after the structure:
    • //method for printing out the information about the objects
      void printBook(Books_t book);
      
    • The implementation of the function should be placed into the structBooks8.cpp file:
    • void printBook(Books_t book)
      {
      	cout << book.title;
      	cout << " " << book.year << endl;
      }
      

      3. Specify two object names (e.g. Pushkin, Chekhov).

    • Open the main.cpp file and inside the main function add the code to create two objects of the structure type:
    • Books_t Pushkin;
      Books_t Chekhov;
      

      4. In the main program, create at least 2 books, display summaries on these books.

    • After the objects' definitions add the code to initialise the members (fields) with the particular values. Ask user to enter one of the fields value, e.g. the year of the book:
    • Pushkin.title = "Eugene Onegin";
      Pushkin.year = 1823;
      
      Chekhov.title = "Three Sisters";
      cout << "Enter year of Chekhov work Three Sisters: "<cin >> Chekhov.year;
      
    • Print out the information about the books using the printBook method:
    • cout << "Pushkin's work is:\n ";
      printBook(Pushkin);
      cout << "And Chekhov's:\n ";
      printBook(Chekhov);
      
      system("pause");
      
    • Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 1:

    To do: Create a Cars_t structure to store an information about the cars. Add the members (fields) about the car's color, car's brand and year of issue. Create at least 4 objects and output information about those objects, using a printCars method.

    Note: The signature of the printCars method should be as follows:

    void printCars(Cars_t car);

    Expected output:

    Task 1:
    Enter car's brand:
    >>audi
    Enter car's color:
    >>grey
    Enter car's year of issue:
    >>1997
    Summary info:
    audi grey 1997
    bmw green 2009
    suzuki white 2015
    honda black 2019
    

    [Solution and Project name: Lesson_8task1, file name L8Task1main.cpp, L8Task1imp.cpp, L8Task1.h]

    Lab 2, arrays of structure type:

    To do: Create a Toys_t structure for storing data about the toys for sale. Add the following properties (members) of an object:

    • toy's title of string type
    • age of children to play with that toy (integer type)

    Tasks:

    1. Implement a method for printing out the information about the objects:
    2. void printBook(Toys_t toy);
    3. Implement a method for printing out the toys for small children (up to 4 years old):
    4. void printToy4(Toys_t toy);
    5. Specify an array of objects toys. Because structures are types, they can also be used as the type of arrays to construct tables or databases of them.
    6. In the main program, create at least 4 elements of the array, display summaries on those toys.

    Expected output:

    Enter toy's title:
    >>cat
    Enter child's age:
    >>2
    Summary info:
    car 3
    doll 4
    crocodile 6
    cat 2
    Summary info for small children:
    car 3
    doll 4
    cat 2
    

    ✍ How to do:

    • To do the lab create empty console application with a name Lesson8Toys. Add files: main8.cpp, structToys8.cpp, structToys8.h.
    • Include all the needed libraries into the code of those files.
    • 1. Create a Toys_t structure for storing data about the toys for sale

    • The structure must be defined inside a header file. So, open the structToys8.h and add the code to define the structure with two properties (members), they are title and age:
    • struct Toys_t
      {
      	string title;
      	int age;
      };
      

      2. Implement a method for printing out the information about the objects.

    • Also inside the header file you should define the method with a parameter of Toys_t type, to accept a particular toy from the main program. Add the code after the structure:
    • //method for printing out the information about the objects
      void printToys(Toys_t toy);
      
    • The implementation of the function should be placed into the structToys8.cpp file:
    • void printToys(Toys_t toy)
      {
      	cout << toy.title;
      	cout << " " << toy.age << endl;
      }
      

      3. Implement a method for printing out the toys for small children (up to 4 years old)

    • Inside the header file define the method with a parameter of Toys_t type:
    • //method for printing out the toys for small children
      void printToy4(Toys_t toy);
      
    • The implementation of the function should be placed into the structToys8.cpp file:
    • void printToy4(Toys_t toy)
      {
      	if (toy.age <= 4) {
      		printToys(toy);
      	}
      }
      

      4. Specify an array of objects toys.

    • Open the main.cpp file and inside the main function add the code to create an array of objects of the structure type:
    • Toys_t toys[4];
      

      5. In the main program, create at least 4 elements of the array, display summaries on those toys.

    • After the objects' definitions add the code to initialise the members (fields) with the particular values. Ask user to enter the values of one array element:
    • toys[0].title = "car";
      toys[0].age = 3;
      toys[1].title = "doll";
      toys[1].age = 4;
      toys[2].title = "crocodile";
      toys[2].age = 6;
      cout << "Enter toy's title: " << endl;
      cin >> toys[3].title;
      cout << "Enter child's age: " << endl;
      cin >> toys[3].age;
      
    • Print out the information about the toys using the printToys method, and information about the toys for small children:
    • cout << "Summary info:\n ";
      for (auto x: toys)
      	printToys(x);
      cout << "Summary info for small children:\n ";
      for (auto x : toys)
      	printToy4(x);
      
      system("pause");
      
    • Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 2:

    To do: Create a Tours_t structure to store an information about the tours for tourists. Add the members (fields) to implement the following info about the tour: country name, number of people, number of days, country rate (of double type). Create a method to print the data, and also method of the structure to calculate the cost of a trip based on: number of people * number of days * country rate. Inside the main function specify an array of objects tours. Both methods must be called for the array elements.

    Note: The signature of the printTourCost method should be as follows:

    // returnes the result of calculation, double type
    double printTourCost(Tours_t tour);

    Expected output:

    Task 2:
    Summary info:
     Sweden: people 2, days 3, rate 155.5
     the price is 933
    Norway: people 1, days 3, rate 265.5
     the price is 796.5
    UK: people 2, days 4, rate 455.5
     the price is 3644
    

    [Solution and Project name: Lesson_8task2, file names L8Task2main.cpp, L8Task2imp.cpp, L8Task2.h]

    Lab 3, Pointers to structures:

    To do: Create a Movies_t structure for storing data about the movies. Add the following properties (members) of an object:

    • movie's title of string type
    • the year of issue (integer type)

    Specify an array of movies (ask user to enter the info of one film). Implement a method for printing out the information about the objects, use the pointer to those objects and arrow operator.

    Expected output:

    Please, enter a title: 
    >>Matrix
    Please, enter year: 
    >>1999
    
    Summary information:
    Matrix 1999
    Titanic 1997
    

    ✍ How to do:

    • To do the lab create empty console application with a name Lesson8Movies. Add files: mainMovies8.cpp, structMovies8.cpp, structMovies8.h.
    • Include all the needed libraries into the code of those files.
    • The structure must be defined inside a header file. So, open the structMovies8.h and add the code to define the structure with two properties (members), they are title and year:
    • struct Movies_t {
      	string title;
      	int year;
      };
      
    • Also inside the header file, you should define the method with a parameter of Movies_t type, to accept an array of movies from the main program. Add the code after the structure:
    • //method for printing out the information about the movies array with n elements
      void printMovies(Movies_t* movie, int n);
      
    • The implementation of the function should be placed into the implementation - structMovies8.cpp file:
    • void printMovies(Movies_t* array, int n) {
      	Movies_t *ptr = array;
      	for (int i = 0; i < 2; i++) {
      		cout << ptr->title << " " << ptr->year << endl;
      		ptr++;
      	}
      }
      
      *ptr is a pointer to point at the location which *array pointer points at.
      The arrow operator (->) is a dereference operator that is used exclusively with pointers to objects that have members. This operator serves to access the member of an object directly from its address.
    • Open the mainMovies8.cpp file and inside the main function add the code to create an array of objects of the structure type and a pointer to point at that array:
    • Movies_t amovie[3];
      Movies_t * pmovie;
      
      pmovie = amovie;
      
    • After the objects' definitions add the code to initialise the properties (fields) with the particular values. Ask user to enter the values of one array element:
    • amovie[1].title = "Titanic";
      amovie[1].year = 1997;
      cout << "Enter title: ";
      cin >> pmovie->title;
      cout << "Enter year: ";
      cin >> pmovie->year;
      
    • Print out the information about the movies using the printMovies method:
    • cout << "\nThe summary:\n";
      printMovies(amovie, 2);
      
      system("pause");
      
    • Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 3:

    To do: Create an Employee_t structure to store an information about the employees of some company. Add the members (fields) to implement the following info about the employees: name, department, phone, salary. Specify an array of employees. Implement a method for printing out the information about the objects, use the pointer to those objects and arrow operator. Also, create a smallSalary method to print out information about the employees, whose salary is less than 30 000 roubles.

    Note: The signature of the smallSalary method should be as follows:

    void smallSalary(Employee_t* array, int n);

    Expected output:

    Task 3:
    Summary info:
    Ivanov: bookkeeping department, t. 233-33-33, 28000 roubles
    Petrov: IT department, t. 233-33-34, 45000 roubles
    Sidorov: client department, t. 233-33-35, 25000 roubles
    
    Salary is less than 30 000 roubles:
    Ivanov
    Sidorov
    

    [Solution and Project name: Lesson_8task3, file names L8Task3main.cpp, L8Task3imp.cpp, L8Task3.h]

    Lesson # 7. Pointer Basics

    Theory

    Pointer Basics

    • Pointers are way of referring to the location of a variable. Instead of storing a value like 5 or the character ‘c‘, a pointer’s value is the location of another variable.
    • The pointer variables have a size (a number of bytes in memory), a name, and a value. They must be declared and initialized.
    • «Pointer» (by itself) is not a type. It is a type constructor — a language construct which, when applied to another type, gives us a new type. In particular, adding a star (*) after any type names the type, which is a pointer to that type. For example:
    • /*
      declares a variable with the name my_char_pointer 
      with the type pointer to a char 
      (a variable that points to a character)
      */
      char * my_char_pointer; // pronounced "char star my char pointer"
      Declaring a pointer
    • The declaration of the pointer tells us the name of the variable and type of variable that this pointer will be pointing to.
    • Assigning to a pointer
    • We can assign to pointers, changing their values. In the case of a pointer, changing its value means changing where it points.
    • We have to initialize a pointer (giving it something to point at) before we use it for anything else.
    • If we do not initialize a pointer before we use it, we have an arrow pointing at some random location in our program (it may cause the program’s crash).
    • To get an arrow pointing at some address of that cell in memory, we need a way to name that box, and then we need to use the & operator (the operator is named the «address-of» operator). Conceptually, the & operator gives us an arrow pointing at its operand.
    • /* you can see code that declares an integer x 
      and a pointer to an integer xPtr */
      int x = 5;
      int *xPtr;
      xPtr = &x; // sets the value of the variable xPtr to the address of x
    • the value of x is initialized to 5 on the same line in which it is declared;
    • the value of xPtr is initialized to the location of x;
    • after it is initialized, xPtr points to the variable x.
    • The code &x = 5; will not compile. A programmer can access the location of a variable, but it is not possible to change the location of a variable.
    • Dereferencing a pointer

    • Once we have arrows pointing at locations of variables, we want to make use of them by «following the arrow» and operating on the box it points at the end of the arrow (when the value of the variable is changing). Following the arrow is accomplished using the star symbol *, a unary (унарный) operator that dereferences a pointer.
    • 6
      7
      
      // An example of the use of the derference operator: 
      *xPtr = 6; // changes the value that xPtr points to 6
    • Notice that the green arrow indicates that this line has not yet been executed, hence x still has the value 5 in the conceptual representation. Once line 7 is executed, however, the value will be 6.
    • Two contexts in which you will see the star (*) symbol, don’t mix them:
      1. In a variable declaration, such as int *p;, the star is part of the type name, and tells us that we want a pointer to some other type (in our example, int * is the type of p).
      2. When the star is the dereference operator. For example, the code r = *p; gives the variable r a new value, namely the value inside the memory cell that p points to. The code *p = r; changes the value inside the memory cell that p points at to be a new value, namely the value of the variable r.

    • When you work with pointers, you will use the star first to declare the variable and then later to dereference it. Only variables that are of a pointer type may be dereferenced.
    • int * q = &y; // is the same as the two statements:
      int *q; 
      q = &y;
      Summarizing
    • There are only three basic pointer actions — declaring, assigning (including initializing), and dereferencing.

    Correct version of swap

    Solution: We have to pass the swap function pointers to the original variables a and b, as it follows below:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    #include <iostream>
    using namespace std;
     
    void swap(int *x, int *y) {
    	int temp = *x; // temp temporarily stores the value that x points to, =3
    	*x = *y; // we take the value that y points to, which is the value of b (=4) 
                      //and store that in the value that x points to, namely the variable a
    	*y = temp; // we take the temp = 3 and store that into the integer that y points to, 
                        //which is the variable b
    }
     
    int main() {
    	int a = 3;
    	int b = 4;
     
    	swap(&a, &b);
    	cout<<"a = "<< a<< ", b = "<<  b << endl;
    	system("pause");
    	return 0;
    }
      
    function swap takes two arguments, x and y which are pointers to integers;
    as we access the values of the integers that x and y point to in the code inside swap, we’re going to have to de-reference x and y. And so, that’s why we’ll see these stars (*) in front of x and y throughout the code;
    inside the main, instead of passing in a and b, we now have to pass in the address of a and address of b.

    A program and memory

    • On a 32-bit machine, where addresses are 32 bits in size, the entire memory space begins at 0x00000000 (in hex, each 0 represents 4 bits of 0) and ends at 0xFFFFFFFF (recall that 0x indicates hexadecimal, and that each F represents four binary 1’s). Every program has this entire address space at its disposal and there is a convention for how a program uses this range of addresses.
    • Let’s look at the picture to understand where in memory a program’s various components are stored.

      Null
    • When we use NULL, we’re going to indicate that it does not point at anything. Whenever we have NULL, we can use the pointer itself (which just has a numeric value of 0), however, we cannot follow the arrow (as it does not point at anything).
    • The NULL pointer has a special type that we have not seen yet — void *. A void pointer indicates a pointer to any type, and is compatible with any other pointer type — we can assign it to an int *, a double*, or any other pointer type we want.

    Accessing an Array

    • Accessing an array element using pointer arithmetic works fine, and sometimes is the natural way to access elements. But in the case when we just want the n-th element of an array, it would be cumbersome to declare a pointer, add n to it, then dereference it.
    • Let’s look at an example of a function that prints the elements of an array and uses pointer manipulation to access those elements:
    • // * array : the name of the array is a pointer to its first element, that is 3
      void printArr(int *array, int n) { 
      	int *ptr = array; // *ptr is a pointer to point at the loaction which *array pointer points at
      	for (int i = 0; i < n; i++) {
      		cout << *ptr; // 1st step output 3, 2dt step output 1, 3d step output 7,
                      // to make pointer point at the memory cell of the next element in the array:
                      // example address ptr = 0x00b5f9a0
      		ptr++;  // 1st 0x00b5f9a4, 2nd 0x00b5f9a8, 0x00b5f9ac, 
                              // no element in the array, but there be no error
                              // it would cause the problem if we dereference pointer 
      	}
      }
      int main(){
      	int arr[4] = { 3,1,7,2 };
      	printArr(arr, 4);
      }
    • We can achieve this goal more succinctly by indexing the array. When we index an array, we write the name of the array, followed by square brackets containing the number of the element we want to refer to. It is important to note that in C++, array indexes are zero-based — the first element of the array is myArray[0].
    • // * array : the name of the array is a pointer to its first element, that is 3
      void printArr(int *array, int n) { 
           for (int i = 0; i < n; i++) {
      	 cout << array[i]; // 1st step output 3, 2dt step - 1, 3d step - 7, and then 2
           }
      }
      int main(){
      	int arr[4] = { 3,1,7,2 };
      	printArr(arr, 4);
      }

    Labs and tasks

    Lab 1:
    To do: Create a function to calculate the addition of pointer and a variable of integer type. That is function must return sum of pointer and variable value.

    Note 1: The signature of the function should be as follows:

    int addP(int var1, int var2);

    Expected output:

    please, enter the first number (for pointer):
    >>>2
    please, enter the second number (to add):
    >>>500
    the result: pointer + 500 = 502
    

    ✍ How to do:

    1. To do the lab create empty console application with a name Lesson7. Add files: main7.cpp, string7.cpp, string7.h.
    2. Include all the needed libraries and files.
    3. Open the main7.cpp file in the code editor. Type the code to output a message for the user, and input the value of two variables. The first of them is for pointer to point to the location of it, and the second — to add to that pointer:
    4. cout << "Lab 1:" << endl;
      cout << "please, enter the first number (for pointer): "<< endl;
      int var1; 
      cin >> var1;
      cout << "please, enter the second number (to add): " << endl;
      int var2; 
      cin >> var2;
      
    5. After, let’s turn to string7.h file and include all the needed directives:
    6. #pragma once
      #ifndef STRING7_H
      #define STRING7_H
      
      #include 
      // your code is here
      #endif
      
    7. The signature of the function was recommended in the task text, let’s add that code with a comments of the task text:
    8. //lab 1: Create a function to calculate the addition of pointer and a variable of integer type
      int addP(int var1, int var2);
      
    9. Now, let’s create the implementation of the function. To do this open the string7.cpp file, include all the directives you need, and add the code:
    10. //lab 1: to calculate the addition of pointer and a variable of integer type
      int addP(int var1, int var2) {
      	int* p_var = &var1;
      	return *p_var + var2;
      }
      
      Here p_var is initialized to the location of var1. Function returs a derference operator — *p_var — which means we take the value that p_var points to (that is the value of var1) and add the value of var2 to it.
    11. Now you can call the function we’ve created and print the results. You must do it inside the main7.cpp file:
    12. cout << "Result:" << endl;
      cout << "pointer + " << var2 << " = " << addP(var1,var2) << endl;
      
    13. Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 1:

    To do: Create an application with a function that takes two arguments, they are integer numbers (var1 and var2), and prints the following calculations with its arguments, using pointers (p1 and p2):

    1) multiplication of pointer and variable: p1 * var1
    2) addition of pointers:  p1 + p2
    3) changing the value of var1 = 5 using pointer p1
    4) changing the address of pointer: p1(address) = p2(address)
    

    Note 1: To change the value of a variable:

    int* p1 = &var1; // if p1 is a pointer
    *p1 = 1; // 1 is a new value for the variable

    Note 2: The signature of the function must be as follows:

    void task1(int var1, int var2);

    Expected output:

    Task 1:
    please, enter the first var value:
    >>5
    please, enter the second var value:
    >>10
    multiplication of pointer and variable: 25
    addition of pointers: 15
    the result of changing the value of var1, var1 = 5
    the result BEFORE changing the address, p1 = 0098F7E8
    the result of changing the address, p1 = 0116FC90
    

    [Solution and Project name: Lesson_7task1, file name L7Task1main.cpp, L7Task1imp.cpp, L7Task1.h]

    Accessing an array

    Lab 2, Arrays:
    To do: An array of integers is given (1, 2, 3, 4, 5, 6, 7, 8, 9). Make every second element being set to 0 (that is even elements must be = 0). You should use indexing the array.

    Note 1: The signature of the function should be as follows:

    void DelEveryEven(int* array, int n);

    Expected output:

    Lab 2, Arrays:
    The array before lab is done:
    1 2 3 4 5 6 7 8 9
    Result:
    1 0 3 0 5 0 7 0 9
    

    ✍ How to do:

    1. To do the lab open the application you've created for lab1 or, if you haven't done it, so make the next: Create empty console application with a name Lesson7. Add files: main7.cpp, string7.cpp, string7.h.
    2. Include all the needed libraries and files (if you didn't do it before).
    3. Open the main7.cpp file in the code editor. Type the code to output a message for the user, and to initialize an array in the same line that you declare it:
    4. cout << "Lab 2, Arrays:\n";
      int my_arr[] = { 1,2,3,4,5,6,7,8,9 };
      
    5. Print the array elements before lab is done:
    6. cout << "The array before lab is done: " << endl;
      for (auto x : my_arr) {
      	cout << x << " ";
      }
      
    7. After, let's turn to string7.h file and include all the needed directives (if you didn't do it before for the lab1):
    8. #pragma once
      #ifndef STRING7_H
      #define STRING7_H
      
      #include 
      
      #endif
      
    9. The signature of the function was recommended in the task text, let's add that code with a comments of the task text:
    10. // lab 2, arrays: An array of integers is given (1, 2, 3, 4, 5, 6, 7, 8, 9). 
      // Make every second element being set to 0
      void DelEveryEven(int* , int);
      
    11. Now, let's create the implementation of the function. To do this open the string7.cpp file, include all the directives you need, and add the code:
    12. //lab 2, arrays:  An array of integers is given. 
      // Make every second element being set to 0 (that is even elements must be = 0).
      void DelEveryEven(int* array, int n) {
      	for (int* p = array + 1; p < array + n; p = p + 2) {
      		*p = 0;
      	}
      }
      
      The * array parameter is initialized to the location of the array, that will be passed on.
      Here, as a loop counter we use a pointer to point at the address of the 1-st array element+1.
      Let's consider the line int* p = array + 1;.

    13. array returns the memory cell of the first element. But we must make the second element being set 0. So, we have array + 1.
    14. Having *p = 0 we dereference the pointer, and we make the second element equal to 0.
    15. To do the same manipulations with the fourth element (even), we can increment the pointer by 2 (p = p + 2).
    16. array + n means the memory cell of the first element plus n, which is 9. This provides an exit from the loop.
    17. Now you can call the function we've created and print the results. You must do it inside the main7.cpp file:
    18. DelEveryEven(my_arr, 9);
      cout << "Result: " << endl;
      for (auto x : my_arr) {
      	cout << x << " ";
      }
      cout << endl;
      
    19. Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 2:

    To do: An array of positive and negative integers is given. Create an application with a function that sets its negative elements to positive values.

    Note: The signature of the function should be as follows:

    void SetNegToPos(int* array, int n);

    Expected output:

    Task 2:
    The array before lab is done:
    1 -2 3 4 5 -6 7 8 -9
    Result:
    1 2 3 4 5 6 7 8 9
    

    [Solution and Project name: Lesson_7task2, file name L7Task2main.cpp, L7Task2imp.cpp, L7Task2.h]

    String characters access with pointer indexing

    Lab 3:
    To do: Reverse the order of characters in the string. To do this, define a pointer to the last character and, moving two pointers from the beginning and end of the line to the middle, swap the corresponding characters.

    Note 1: To access the characters of a string with pointer indexing you should use char type for that string:

    char str[] = "Hello world";

    Note 2: The signature of the function should be as follows:

    void reverseString (char * str);

    Expected output:

    // lab 3:
    The string before lab is done:
    Hello world
    The string after lab is done:
    dlrow olleH
    

    ✍ How to do:

    1. To do the lab open the application you've created for lab1 or, if you haven't done it, so make the next: Create empty console application with a name Lesson7. Add files: main7.cpp, string7.cpp, string7.h.
    2. Include all the needed libraries and files (if you didn't do it before).
    3. Open the main7.cpp file in the code editor. Type the code to output a message for the user, and to initialize the array of char type (the string will be treated as an array of chars):
    4. cout << "Lab 3:" << endl;
      char str[] = "Hello world"; 
      cout << "The string before lab is done: " << str << endl; 
      
    5. After, let's turn to string7.h file and include all the needed directives (if you didn't do it before for the lab1):
    6. #pragma once
      #ifndef STRING7_H
      #define STRING7_H
      
      #include 
      
      #endif
      
    7. The signature of the function was recommended in the task text, let's add that code with a comments of the task text:
    8. // Lab 3: Reverse the order of characters in the string. 
      void reverseString(char* str);
      
      str is initialized to the location of str.
    9. Now, let's create the implementation of the function. To do this open the string7.cpp file, include all the directives you need, and add the code:
    10. // Lab 3: Reverse the order of characters in the string. 
      void reverseString(char* str) {
      	char* str1 = str;
      	char* res = nullptr;
      	while (*str1) {
      		res = str1; 
      		*(str1++); 
              } // end of while
      // ...
      } // end of function
      
      Here, we define a pointer to string's first character. The line (char* res = nullptr;) returns a "null pointer", that is 0x00000000 address. Then, we use the while loop to iterate over the array's elements addresses. After the loop, the variable res will get the value of the address of the last character of the string, that is can be 0x00cffae6, for example, for "d" character).
    11. Then we're going to assign the value of the characters to the *str variable, moving the pointer from the last character to the middle. To do it we use the temporary variable t. And at the same time we're going to substitude the values of the array elements, beginning from the last element and assigning the value of the first element to it. We should do the dereferencing for this purpose:
    12. 	auto l = res;
      	while ((l) > (str)) {
      		auto t = *l; // temporary variable to store the values, moving from the last, 'd'
      		*l = *str; // dereferencing, we take the value that *str points to, which is the value of str 
                                 //and store that in the value that *l points to
      		*str = t; // changes the value that *str points to
      		l--; // moving from the last address to the middle
      		str++; // moving from the first address to the middle
      	}
      
      
    13. Now you can call the function we've created and print the results. You must do it inside the main7.cpp file:
    14. reverseString(str);
      cout << "The string after lab is done: " << str << endl;
      
    15. Add the code to return a value 0 inside the main function. Run the program and check the output.
    Task 3:
    To do: There is a string that contains the positive integer ('Happy 2021 year to u!'). Create a function to display the string containing this number.

    Note 1: Use the following function signature. It returns integer (you should make a number using the digits):

    void numbFromStr(char* str);

    Note 2: The result must be of string type, so you should include the string library:

    #include <string>

    Note 3: to check if the character is a digit:

    if (isdigit(yourCharacter)) {
       // ...
    }

      
    Expected output:

    Task 3:
    The string for the task is: Happy 2021 year to u!
    the substring of numbers: 2021
    

    [Solution and Project name: Lesson_7task3, file name L7Task3main.cpp, L7Task3imp.cpp, L7Task3.h]

    * Extra Task (complicated):
    To do: There is a string that contains the positive integer ('Happy 2021 year to u!'). Return the appropriate number .

    Note 1: Use the following function signature. It returns integer (you should make a number using the digits):

    int strToInt (char * str);

    Note 2: to convert the digital character C to the corresponding number from 0 to 9, you must subtract the zero character code from it: C - '0'.
    Expected output:

    Extra Task:
    The string for the task is: Happy 2021 year to u!
    There is a number: 2021
    

    Lesson # 6. Using strings

    Theory

    String as an array of characters

    • To work with a string the string library must be included:
    • #include <string>
    • Variables of string type can be understood as an array of characters.
    • A specific character in a string can be accessed as in a regular array, that is, by its index:
    • string str="it's possible to understand it";
      cout << str[2] << endl; // output: '
      for (int i = 0; i <= s.size(); i++) { // to iterate over the characters of a string
      		if (s[i] == ' ')
      			//to do sth
      	}

    String functions

    • Find()
    • size_t find (const string& str, size_t pos = 0) const;
    • Searches the string for the first occurrence of the sequence specified by its arguments.
    • When pos is specified, the search only includes characters at or after position
    • pos, ignoring any possible occurrences that include characters before pos.

    • size_t is an unsigned integral type, able to represent the size of any object in bytes
    • npos constant — Maximum value for size_t (usually = 4294967295)
    • This value, when used as the value for a len (or sublen) parameter in string’s member functions, means «until the end of the string».
    • As a return value, it is usually used to indicate no matches.
    • This constant is defined with a value of -1, which because size_t is an unsigned integral type, it is the largest possible representable value for this type.
    • The method to find how many times the subsctring occurs in the string:
      string str="it's possible to understand it";
      string substr="it";
      size_t f = -1; 
      while (true) // infinite loop
       {
          // f = str.find(substr); // f will be equaled to 0
          // 'f+1' is required to move to the next position after found match
          f = str.find(substr, f+1); // in the 2-nd iteration f = 28
          // in the 3-rd iteration f = 4294967295, it means that there is no more matches 
          // string::npos = 4294967295
          if (f == string::npos)
               break;
        }

      Escape sequences are used to represent certain special characters within string literals and character literals: \‘ single quote

      char c = '\''

    Strings as char and pointers

    Labs and tasks

    To do all the tasks and labs of this lesson you must create three files:

    1. a header file (basicStrings.h) (functions definitions for all the tasks must be placed here);
    2. a basicStrings.cpp file (the implementations of the functions with comments for all the tasks must be placed here)
    3. a main.cpp must provide prompts for user, calling created functions and output results for all the tasks.
    4. Each function should be accompanied by a comment about what it is intended for, and a number of the task must be provided.

    String as an array of characters

    Lab 1:

    To do: A string (variable s) and character (variable c) are given (ask user to input them). Check if the character c is among the characters in the string. Create a function named checkIfChar to do the task. The function must return 1 if entered character is found or 0 otherwise.

    Note 1: The signature of the function must be as follows:

    bool checkIfChar(string s, char c)

    Expected output:

    lab 1
    Enter a sentence:
    >>> Hello world
    Enter character:
    >>> o
    result:
    1
    

    ✍ Algorithm:

    1. Open visual studio and create a console application named Lesson6. While creating, check the Empty project (Пустой проект) item.
    2. Two .cpp files must be added to the source files folder of the project (basicStrings.cpp and main.cpp) and one header file must be added to the Header files folder.
    3. Open the main.cpp file’s code and add all the libraries we need to do the lab:
    4. #include 
      #include  //
      #include  // is needed to work with string type
      using namespace std;
      
    5. Inside the main function, ask user to input a sentence and assign the input value to str variable. Don’t forget to declare the variable:
    6. int main() {
      	cout << "lab 1:" << endl;
      	cout << "Enter a sentence:" << endl;
      	string str; // declaration of the variable
      	cin >> str; // input or assigning a value
        // ..
      }
      
    7. Then, ask user to input a character to find it in the sentence. Set the input value to a variable c:
    8. cout << "Enter character :" << endl;
      	char c;
      	cin >> c;
      
    9. Now, we’re going to create a function to check if the input charecter is within the input sentence. The function must be supplied with two values — the sentence (str) and character (c), they are the arguments of the function. Add the signature of the function before the main function:
    10.  //lab 1: Check if the character c is among the characters of the string
      bool checkIfChar(string s, char c)
      {
      	// to do
      }
      
    11. We’re going to itereate over the characters of the string using for loop. Inside the the loop body we must check if a current character of the string matches the character c. If it does, the function must return 1, in the case when it doesn’t, the function returns 0.
    12. for (int i=0;i<= s.size();i++){
      		if (s[i]==c)
      			return 1;
      		else
      			return 0;
      	}
      
    13. Come back to the main function code and call the function. The results of the function must be printed out, so, the calling should be inside cout<< statement:
    14. <span class="blue">cout</span> << <span class="red">"result :"</span> << checkIfChar(str, c) << endl;
    15. Be careful not to forget to add a statement to stay the console window opened:
    16. //...
      system("pause");
      return 0;
      //...
      
    17. Run the program and check the output.
    Task 1:

    To do: Create a function to check if input text contains a combination of letters ‘mo‘. Return 1 (if found) or 0 (if not found). It is not allowed to use any standard functions.

    Note 1: The signature of the function must be as following:

    bool findMo(string s)

    Note 2: To check two or more conditions in if statement you must use && (logical and):

    if (condition_1 && condition_2){
    }

    Expected output:

    task 1
    result for 'Hello world' is:
    0
    ---
    task 1
    result for 'My mom' is:
    result:
    1
    

    Task 2:

    To do: Create a function to check if the value of string variable contains the word ‘cat‘. Return 1 (if found) or 0 (if not found). It is not allowed to use any standard functions.

    Note 1: The signature of the function must be as following:

    bool findCat(string s)

    Expected output:

    task 2
    the string is: Hello world
    result:
    0
    ---
    task 2
    Enter a sentence:
    the string is: my cat
    result:
    1
    
    Task 3:

    To do: A sentence is given: str = "word1 word2 word3 word4". Calculate the number of words in it. It is not allowed to use any string standard functions.

    Note 1: You have to count the number of words by the number of spaces between the words.

    Note 2: Don’t forget to check if the sentence contain extra spaces at the beginning and end of the sentence.

    Note 3: The signature of the created function must be as following:

    void countWords(string s, int& counter)

    Expected output:

    task 3
    Enter a sentence:
    >>>  word1 word2 word3 word4
    result:
    4
    

    Task 4:

    To do: A string is given. Check if its first and last characters match. Create a function named LastAndFirst to do the task. It is not allowed to use any string standard functions (except size() function).

    Note 1: The signature of the created function must be as following:

    bool LastAndFirst(string s)

    Note 2: The size() method of the string can be useful to find the last character (s.size()).

    Expected output:

    task 4
    for sentence Hello world
    the result is:
    false
    ---
    task 4
    for sentence lucky ball
    result is:
    true
    

    String functions

    Task 5:

    To do: Create a function to check if the text contains the word cat. Print the position (order number) of the word in the text. You should use standard find function.

    Note 1: The signature of the created function must be as follows:

    void findCatFunction(string s, string s0)

    Note 2: About find() function:

    s.find(s0) // returns -1 if there are no matches of s0 in the text s

    Expected output:

    task 5
    for text: cat word1 word3 word4
    result :
    cat is found at: 0
    ---
    task 5
    for text: word1 word3 word4
    result :
    cat is not found
    ---
    task 5
    for sentence: word1 cat word3 word4
    result :
    cat is found at: 6
    
    Lab 2:

    To do: Two strings S and S0 are given (they are entered). Find the number of occurrences of the string S0 in the string S.

    Note 1: In the solution, it is convenient to use the find member function of the string class, which returns the position of the occurrence of type size_t (unsigned integer), or the value of string :: npos in case no occurrence was found. Look at the example to understand the way to use them.

    Note 2: The signature of the function must be as follows:

    int countOccurrence(string s, string s0)

    Expected output:

    Lab 2
    string 1: it's possible to understand it 
    string 2: it
    result : 2
    

    ✍ Algorithm:

    1. Open main.cpp file and inside the main function, under the previous task code, add the code to output the number of the task. After that, declare the variables of string type and initialize them with values:
    2. //lab 2
      cout << "lab 2:" << endl;
      string str1, str2;
      str1 = "it's possible to understand it";
      str2 = "it";
      cout << "string 1: " << str1 << "\n string 2: "<< str2 << endl;
      
      \n is used to insert a new line.
    3. Open the implementation file, that is basicStrings.cpp. Add the code of the signature of the function, and also, add comments with explanation of the task:
    4. // lab 2: Find the number of occurrences of the string S0 in the string S
      int countOccurrence(string s, string s0)
      {
         // to do:
      } 
      
    5. The function must return integer type (since int is the type of the function).
    6. The function has two parameters of string type: s is a string containing the sentence, and s0 is a substring which we must find inside the string s.
    7. To find the substring we're going to use the find() standard method and f variable of size_t type (an unsigned integral type). The f variable will store the position of the substring inside the s string. And if there isn't founded substring the f will store 0 number, since it will be increase by 1 (f+1). When the find() function will reach the end of the string, the npos value (npos is a constant — maximum value for size_t (usually = 4294967295)) will be set to f variable:
    8.  size_t f = -1;
       int res = 0; // counter of the numbers of occurrences 
       while (true) // infinite loop
      	{
      		f = s.find(s0,f+1); 
      		if (f == string::npos) // if the end of the string is reached
      			break; // exit loop
      		++res;
      	}
      	return res;
      
      The infinite loop is convenient to use when we don't know how many repetitions of the loop there will be. Here the break operator will be executed only if when seeking the substrings, we will reach the end of the string.
    9. Let's return to the main.cpp file and inside the main function add the call of our function. Since the function will return the integer value, that is the number of occurrences, we must store the results of the function inside the variable:
    10. int counter = countOccurrence(str1, str2);
      cout << "result :"  << counter << endl;
      
    11. Run the program and see the outputs.
    Task 6:

    To do: Two strings S and S0 are given (they are entered). Create a function to remove from string S the last substring that matches S0. If there are no matching substrings, then return string S unchanged.

    Note 1: You can use the rfind member function of the string class to find the last occurrence of a substring, and you can use the erase member function to delete.

    Note 2: Look at the example to understand the way to use them.

    Note 3: The signature of the function must be as follows:

    string eraseLast(string s, string s0)
    {
    	// to do:
            // 
            //
    	return s;
    }

    Expected output:

    task 6:
    string 1: it's possible to understand it
    string 2: it
    result: it's possible to understand
    
    Task 7:

    To do: A string containing at least one space character is given. Return the substring between the first and last space of the string. If the string contains only one space, then return an empty string.

    Note 1: You can use the substr member function of the string class to extract a substring.

    Note 2: Look at the example to understand the way to use them.

    Note 3: The signature of the function and the fragment of its code:

    string betweenSpaces(string s)
    {
    	size_t f1, f2;
    	f1 = s.find(" "); // the position of the first space
    	f2 = s.rfind(" "); // the position of the last space
    	// ...;
            // ...;
    	return  // ...;
    }

    Expected output:

    task 7:
    string: it's possible to understand it
    result : possible to understand
    

    Lesson # 5. Using vector

    Theory

    Vectors

    • A template type is a special type that can take on different types when the type is initialized.
    • std::vector standard library class that provides the functionality of a dynamically growing array with a “templated” type.
    • std::vector uses a template type:

    • Example:

      #include <vector>   // Definition
      using namespace std;
      int main()
      {
      vector<int> mm(5);  // Initialization
      vector<int> a {1, 2, 3, 7};  // Initialization
      // Loop for to iterate and print values of vector
      for (int i=0; i < a.size(); i++)  // size() - Number of elements
         cout << a[i] << " ";
      // Another kind of for loop (foreach) to iterate and print values of vector
      for (auto x : a)
         cout << x << " ";
      for (int& x : a)
         x++;
      }
      To use vector #include directive need to be placed.
    • When initializing a “templated” type, the template type goes inside of < > at the end of the type name:
    • std::vector<char> v1;
      std::vector<int> v2;
      
    • pop_back function removes the last element
    • push_back function adds an element to the end:
    • Example 1:

      #include <iostream>
      #include <vector>
       
      int main()
      {
          // Create a vector containing integers
          std::vector<int> v = {7, 5, 16, 8};
       
          // Add two more integers to vector
          v.push_back(25);
          v.push_back(13);
       
          // print out the particular elements
          cout << v[0] << std::endl;
          cout << v[1] << std::endl;
          cout << v[2] << std::endl;
       
          // Iterate and print values of vector
          for(int n : v) {
              std::cout << n << '\n';
          }
      }

      Example 2:

      #include <vector>
      #include <iostream>
       
      int main() {
      vector<int> v;
      for (int i = 0; i < 100; i++) {
         v.push_back( i * i );
      }
       
      cout << v[12] << std::endl;
       
      return 0;
      }

    Function template

    • A template variable is defined by declaring it before the beginning of a class or function:
    • template <typename T>
      int max(T a, T b) {
        if (a > b) { return a; }
           return b;
      }
      
    • Templated variables are checked at compile time, which allows for errors to be caught before running the program.
    • #include <iostream>
      using namespace std;
       
      template <typename T>
      T max(T a, T b) {
      	if (a > b) { return a; }
      	return b;
      }
      int main()
      {
      	cout << "max(3, 5): " << max(3, 5) << endl; // 5
      	cout << "max('a', 'd'): " << max('a', 'd') << endl; // d
      	cout << "max(\"Hello\", \"World\"): " << max("Hello", "World") << endl; // Hello
      	cout << "max(3, 5, 6): " << max(3, 5, 6) << endl; // error
       
      	system("pause");
      	return 0;
      }
    • A function template defines a family of functions.
    • A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function.
    • An explicit instantiation definition forces instantiation of the function or member function they refer to. It may appear in the program anywhere after the template definition, and for a given argument-list, is only allowed to appear once in the program, no diagnostic required.
    • template<typename T>
      void f(T s)
      {
          std::cout << s << '\n';
      }
       
      template void f<double>(double); // instantiates f<double>(double)
      template void f<>(char); // instantiates f<char>(char), template argument deduced
      template void f(int); // instantiates f<int>(int), template argument deduced
    • Implicit instantiation: When code refers to a function in context that requires the function definition to exist, and this particular function has not been explicitly instantiated, implicit instantiation occurs. The list of template arguments does not have to be supplied if it can be deduced from context.
    • #include <iostream>
       
      template<typename T>
      void f(T s)
      {
          std::cout << s << '\n';
      }
       
      int main()
      {
          f<double>(1); // instantiates and calls f<double>(double)
          f<>('a'); // instantiates and calls f<char>(char)
          f(7); // instantiates and calls f<int>(int)
          void (*ptr)(std::string) = f; // instantiates f<string>(string)
      }

      Note: omitting <> entirely allows overload resolution to examine both template and non-template overloads.

    * resources: 1) https://en.cppreference.com/w/cpp/container/vector

    Labs and tasks

    To do all the tasks and labs of this lesson you must create three files:

    1. a header file (basicVectors.h) (functions definitions for all the tasks must be placed here);
    2. a basicVectors.cpp file (the implementations of the functions with comments for all the tasks must be placed here)
    3. a main.cpp must provide prompts for user, calling created functions and output results for all the tasks.
    4. Each function should be accompanied by a comment about what it is intended for, and a number of the task must be provided.
    Lab:
    The tasks of this lesson will be continuation of this lab.

    To do: An integer N (N > 0) and an integer vector (array) of length N are given. Fill the vector with the first N positive odd numbers: 1, 3, 5,… N. Do not use the conditional statement. Create a oddVectorGenerator() function to do the task.

    Note: To print the resulting vector, hereinafter, you must use the print_vector() function template. The function must be placed inside special header file printVect.h (you should add a new file to your application).

    Copy the print_vector function code and paste it to the printVect.h file:

    #ifndef PRINTVECT_H
    #define PRINTVECT_H
     
    #include <iostream>
    #include <vector>
     
    // note: function templates are always must be inside header files
     
    // function template to output vector
    template<typename T>
    void print_vector(const std::vector<T>& v, char delim = ' ') {
    	for (auto x : v)
    		std::cout << x << delim;
    	std::cout << std::endl;
    }
     
    /* #ifndef PRINT_VECT_H: */
    #endif

    Expected output:

    lab 1
    enter N - the number of vector elements
    >> 25
    1 3 5 7 9 11 13 15 17 19 21 23
    

    ✍ How to do:

    • Create a new console application with a name Lesson 5.
    • In the Source files folder of the Solution Explorer window, add new files: basicVectors.cpp and main.cpp. In the Header Files folder add a new header file: basicVectors.h.
    • Function templates are always placed in header files unlike regular functions. Add a new header file and name it printVect.h. Copy and paste the template function code into it.
    • Open your main.cpp file and include there all the header files that program will need:
    • #include <iostream>
      #include "basicVectors.h"
      #include "printVect.h"
      using namespace std;
      
      
    • Then, you must define an integer vector. You should do it inside the main.cpp file, right after all the included directives:
    • vector<int> v;
      
    • Output the comment to indicate that this is lab 1. Then, ask user to input a number of the vector elements. Set the entered value to the n variable:
    • cout << "lab 1"<< endl;
      cout << "enter N - the number of vector elements";
      int n;
      cin >> n;
      
    • Open your basicVectors.h header file. Include all necessary directives:
    • #pragma once
      #include <iostream>
      #include <vector>
      using namespace std;
      
    • We’re going to define our oddVectorGenerator() function, that must fill the vector with the first N positive odd numbers:
    • void oddVectorGenerator(vector<int>&, int);
      
      We’re going to pass vector parameter by reference (&), because we don’t need to locate a new memory space to store it.
    • Open basicVectors.cpp file to add an implementation of the created function. But first, add all the include directives to the file:
    • #include 
      #include <cassert>
      #include "printVect.h"
      #include "basicVectors.h"
      using namespace std;
      
    • After that, let’s create the oddVectorGenerator() function and all the code it must implement:
    • void oddVectorGenerator(vector<int> &v, int n)
      {
      	for (int i = 1; i < n; i += 2)
      	{
      		v.push_back(i);
      	}
      }
      
      push_back function adds an element to the end of the vector.
      Only odd numbers will be set to vector due to the for loop step=2.
    • Open your main.cpp file and call the function. To output the results call the print_vector() function too:
    • oddVectorGenerator(v, n);
      print_vector(v);
      system("pause");
      
    • Run the program. And proceed with Task 1.
    Task 1:

    To do: A vector is given (you can have the following element values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10). Output its elements in reverse order. Create a function to do it.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    cout << "task 1" << endl;

    Note 2: To use the same variable v in this task you should clear the elements, and then, set new elements to it:

    v.resize(0);
    v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    Note 3: You can create a new vector with the reversed elements.

    Expected output:

    task 1
    before task:
    1 2 3 4 5 6 7 8 9 10
    after task:
    10 9 8 7 6 5 4 3 2 1
    Task 2:

    To do: An integer vector is given. Calculate the number of odd numbers in this vector, as well as the number of positive numbers in it.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Note 2: To use the same variable v in this task you should clear the elements, and then, set new elements to it:

    v.resize(0);
    v = { -1, 2, 3, 4, -5, 6, 7, 8, -9, 10 };

    Note 3: To check if the negative number is odd you should use abs function.

    Expected output:

    task 2
    vector:
    -1 2 3 4 -5 6 7 8 -9 10
    number of positive: 7 number of odd : 5
    
    Task 3:

    To do: An integer vector is given. Output the index of its first even element.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Note 2: To use the same variable v in this task you should clear the elements, and then, set new elements to it:

    v.resize(0);
    v = { -1, 2, 3, 4, -5, 6, 7, 8, -9, 10 };

    Expected output:

    task 3
    vector:
    -1 5 3 4 -5 6 7 8 -9 10
    the first even element number is: 4
    
    Task 4:

    To do: An integer vector is given. Ouput the maximum of its local minima (a local minimum is an element that is less than any of its neighbors: e.g. ... 5 2 7 ... => number 2 is a local minimum, because 2 < 5 and 2 < 7).

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Note 2: To initialize a variable that should store the current value of the maximum local minimum, it is convenient to use the INT_MIN constant from the standard header:

    int max = std::numeric_limits<int>::min();

    Expected output:

    task 4
    vector:
    -1 5 3 4 -5 8 7 8 -9 10
    the maximum of local minima is: 7
    
    Task 5:

    To do: An integer vector A of size N (> 0) is given. Fill it with powers of two from the 1 power to the N: 2, 4, 8, 16,….

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Expected output:

    task 5
    Enter N number:
    >>> 5
    vector:
    2  4  8  16  32
    
    Task 6:

    To do: an integer vector A of size N is given. It contains at least one even number. Find the first and last even number in the given vector. To do the task create getFirstAndLastEvenNumber() function.

    Note 1: Use passing parameters by reference (&) to return two values from a function.

    Note 2: Besides the getFirstAndLastEvenNumber() function you should create one more function of boolean type, to check if the number is even:

    inline bool isEven(int n)
    {
        //
    }

    Note 3: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Expected output:

    task 6
    Enter N number:
    >>> 5
    vector:
    2  12  1  16  3
    the first: 2, the last: 16
    
    Task 7:

    To do: Three integer vectors A, B and C of the same size N are given. You must fill in vector C with values according to the following rule: each of its elements is equal to the maximum of the elements of vectors A and B with the same index.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Note 2: To compare two values you should use the standard max function, for example:

    int maximum = std::max(a, b);

    Note 3: You should check if the sizes of the vectors are equal, use assert() function, for example:

     assert((a.size() == b.size()) && (c.size() == a.size()));

    Note 4: You should create the following function signature:

    void maxInVectors(std::vector<int> &a, std::vector<int> &b, std::vector<int> &c)
    {
    // body function
    }

    Expected output:

    task 7
    A vector:
    0 1 2 3 4 42 6 7 8 422
    B vector:
    9 8 7 6 5 4 3 2 1 0
    vector C:
    9 8 7 6 5 42 6 7 8 422
    

    Extra tasks

    *ExTask 1:

    To do: An integer vectors Ais given. You must create B vector of the same size and fill in the vector with all numbers from vector A that have the digit 2 in decimal notation.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Note 2: In the implementation of the function, use a function that checks whether a given integer has a given digit in its decimal notation. You should implement it yourself:

    bool hasDigit (int n, int digit);

    Note 3: You should check if the sizes of the vectors are equal, use assert() function.

    Note 4: You should use push_back(value) method to add the new value to a vector. The method adds a new element to the end of the vector, for example:

    b.push_back(x);

    Expected output:

    task 6
    vector A:
    0 1 2 3 4 42 6 7 8 422
    vector B:
    2 42 422
    
    *ExTask 2:

    To do: An integer vector is given. Output the length of the largest series of consecutive zeros.

    Note 1: You must complete this task in the same application as Lab 1. Output the task number before the results of this task are printed.

    Expected output:

    task 7
    vector:
    0 1 0 0 0 42 6 7 8 422
    maximum length of 0: 3
    
    *ExTask 3:

    To do: Remove all odd elements from the vector by shifting the remaining elements to its beginning.

    Note 1: You should use the remove_if() standard method, which removes elements from the container that pass a specified test:

    auto newEnd = std::remove_if(a.begin(), a.end(), [](int n)
    	{
    		return // some test;
    	});

    Note 2: To delete the elements from the vector you can use the erase() standard method.

    Expected output:

    task 8
    before task:
    0 1 2 3 4 42 6 7 8 422
    after task:
    0 2 4 42 6 8 422
    
    *ExTask 4:

    To do: A vector of size N and an integer K (0 ≤ K < N) are given. Remove the element with K index from the vector by shifting all the following elements one position to the left and decreasing the vector size by one.

    Note 1: To check the index you can use the following construction:

    if(index < 0 || index > size)
            throw "Incorrect index!";

    Note 2: To delete the elements from the vector you can't use the erase() standard method.

    Expected output:

    task 9
    enter the index to delete
    >>> 2
    before task:
    1 2 3 4 5 6 7 8 
    after task:
    1 2 4 5 6 7 8
    

    Lesson # 4. Enumerations

    Theory

    Enumerations

    The enum type declaration can be in the .cpp file at the top of the code (that is, outside of the functions), as well as in the header files.

    int main()
    {
      enum MyType { A, B, C }; // A=0 B=1 C=2
      enum YourType { D = 2, E, F = 0 }; // E=3
      MyType m = A;
    }
    Each enumerator is associated with a value of the underlying type. When initializers are provided in the enumerator-list, the values of enumerators are defined by those initializers. If the first enumerator does not have an initializer, the associated value is zero. For any other enumerator whose definition does not have an initializer, the associated value is the value of the previous enumerator plus one.
    Enumerations in style of C++11:
    int main()
    {
      enum class Color { Red, Green, Blue };
      Color c = Color::Blue;
    }

    One more example:

    enum Color { red, green, blue };
    Color r = red;
    switch(r)
    {
        case red  : std::cout << "red\n";   break;
        case green: std::cout << "green\n"; break;
        case blue : std::cout << "blue\n";  break;
    }
    // int n = r; // error: no scoped enum to int conversion
    int n = static_cast<int>(r); // OK, n = 21

    Type conversion by static_cast

    Sample 1:

    char c = 97;
    std::cout << static_cast<int>(c) << std::endl; // output 97, but not 'a'

    Sample 2:

    int i1 = 11;
    int i2 = 3;
    std::cout << i1/i2; // 3
    float x = static_cast<float>(i1) / i2;  // output x = 3.66667

    Labs and tasks

    Follow the rules:

    • To do the tasks, you must create a Visual Studio project: Lesson_4. When the tasks are done, it is necessary to upload the Lesson_4 project files (e.g. L4Task1Imp.cpp, L4Task1header.h and L4Task1main.cpp).
    • To do the tasks, you should use such C ++ structures as enumerations and switch statement.
    • All tasks must be done using functions, the results should be checked by assert statement from the header file , calling them from main with different arguments.
    • All functions and files must be accompanied by comments that describe the task.
    Lab 1:

    To do: Create a function (named printDay) that inputs the days of week (from 1 to 7) and returns the full name of the corresponding day (if 1 is entered, so function must print «Monday», etc.)

    Note: Add a header file to your project. Type there a declaration of the enumeration and the signature of your method:

    // enum type for representing a day: MON for Monday, etc.
    enum Day {MON=1, TUE, WED, THE, FRI, SAT, SAN };
     
    // prints given day to the standard output
    void printDay(Day);

    The resulting example:

    please enter the number of a day of a week:
    >> 2
    Tuesday
    

    [Solution and Project name: Lesson_4, file name L4Lab1Imp.cpp, L4Lab1main.cpp, L4Lab1header.h]

    ✍ How to do:

    1. Open Microsoft Visual Studio. Create a new console project, name your project Lesson_4. Among the Additional options mark Empty project and nothing more. Click Finish button.
    2. In the Solution Explorer window find a Source files folder, click the right mouse button on it and select Add -> New Item. We’re going to create two .cpp files. Call them as it is written in this lab description.
    3. In the Solution Explorer window find a Header files folder, click the right mouse button on it and select Add -> New Item. We’re going to create .h file. Give it a name as it is written in this lab description.
    4. First, let’s define an enumeration to store the names of the week days. The definition must be placed inside the header file. So, open header file and add the code:
    5. #ifndef L4LAB1HEADER_H
      #define L4LAB1HEADER_H
      // type for representing a day of a week
      enum Day { MON = 1, TUE, WED, THE, FRI, SAT, SAN };
       
      #endif L4LAB1HEADER_H
    6. Add the definition of our function printDay(). It must accept one parameter – the number of the day of a week (the type of parameter is Dayenum). The function definition must be placed inside the header file too:
    7. // prints given day to the standard output
      void printDay(Day);
    8. Open the code of L4Lab1Imp.cpp, we’re going to create an implementation of our function. Include the header file and std namespace:
    9. #include <iostream>
      #include <cassert>
      #include "L4Lab1header.h"
      using namespace std;
    10. Add a signature of your function:
    11. // prints given day to the standard output
      void print_month(Day d) {
        // ...
      }
    12. To check the day number we need to use Switch statement. Add the code inside the function scope:
    13. switch (d)
      	{
      	case 1:
      		std::cout << "Monday" << std::endl;
      		break;
      	case 2:
      		std::cout << "Tuesday" << std::endl;
      		break;
      	case 3:
      		std::cout << "Wednesday" << std::endl;
      		break;
      	case 4:
      		std::cout << "Thursday" << std::endl;
      		break;
      	case 5:
      		std::cout << "Friday" << std::endl;
      		break;
      	case 6:
      		std::cout << "Saturday" << std::endl;
      		break;
      	case 7:
      		std::cout << "Sunday" << std::endl;
      		break;
      	}
    14. Open the L4Lab1main.cpp. Include the header file and needed libraries:
    15. #include <iostream>
      #include <cassert>
      #include "L4Lab1header.h"
      using namespace std;
    16. Inside the main function ask user to enter an integer and assign the value to dayNumb variable.
    17. int dayNumb;
      cout << "please enter the number of a day of a week:";
      cin >> dayNumb;
    18. To call the function we need to pass it one parameter of out enumeration type (Day type). But all we have is dayNumb variable of integer type. We can use static_cast to convert the variable to Day type:
    19. Day d;
      d = static_cast<Day>(dayNumb);
    20. Now we can call a function:
    21. printDay(d);
    22. Run the program and check the output.
    Task 1:

    To do: Define a Month enumeration data type to represent the month.
    Create a function (named printMonth()) that will display the full month name for the passed short month name. Use a switch statement.

    Note 1: Create another function (named inc()) that displays the next month for the passed short month name.

    Note 2: add the header file. Inside the file add the enum and your function declaration:

    // type for representing a month: JAN for January, etc.
    enum Month {JAN=1, FEB, MAR, /* TODO: ... */ DEC};
    // prints given month to the standard output
    void printMonth(Month);
    // return next month
    Month inc(Month);

    Note 2: Look at the code below and understand it (using static_cast):

    (m == DEC)? JAN: static_cast<Month>(m + 1);
    Test this function from the main:
     assert (JAN == inc (DEC));

    The resulting example:

    Full name for JUN is: June
    The next month for DEC is: 1

    [Solution and Project name: Lesson_4, file name L4Task1Imp.cpp, L4Task1main.cpp, L4Task1header.h]

    Task 2:

    To do: Within the previous task create a function (named dec()) that, for the entered month, displays the preceding month.

    Note 1: Test this function from main:

    assert (JAN == dec (FEB));

    Note 2: Add the declaration into the header file:

    // return previous month
    Month dec(Month);

    The resulting example:

    Full name for JUN is: June
    The previous month for JUN is: 5

    [Solution and Project name: Lesson_4, file name L4Task2Imp.cpp, L4Task2main.cpp, L4Task2header.h]

    Task 3:

    To do: {2 points} Create function of Boolean type that returns True (or 1) if the year (positive integer) is a leap year, and False (or 0) otherwise.

    Note 1: A leap year is a year that is divisible by 4, except for those years that are divisible by 100 and not divisible by 400.
    Note 2: Add some tests to the main function. 2000 and 2012 are leap years, 2100 is a common year.

    Note 3: Add the declaration into the header file:

    // check if given year is leap
    bool is_leap(int);

    The resulting example:

    please enter the year:2000
    year is leap - 1

    [Solution and Project name: Lesson_4, file name L4Task3Imp.cpp, L4Task3main.cpp, L4Task3header.h]

    Lesson # 3. For Loops and While Loops. References briefly

    Theory

    Note about for loop

    The for loop allows you to use several counters: the initialization and increment sections can contain several operators connected by the operator «,» (comma)

    int a = 0, b = 0;
    for (a = 1, b = 8; a < b; ++a, --b) {
        // empty body
    }
    cout << a << " " << b << endl; // output 5   4

    References

    References are not objects; they do not necessarily occupy storage:

    void double_numb(int& numb) {
    	numb *= numb; // 'numb' is the same as main()'s 'x'
    }
    void main(){
    int x = 2;
    	double_numb(x);
    	cout << x << '\n';
    	system("pause");
    }
  • References are the other name of the variable:
  • int main(){
      int a = 5;
      int& ra = a;
      ra = 3;
      std::cout << a; // output 3!
      system("pause");
    }

    Labs and tasks

    • Create an empty application with a name Lesson_3. All the tasks and labs must be done within this application. When one task is ready, exclude the .cpp file of the task and add a new file to the application to do the next task.
    • Or you can do all tasks within the same header and source file. But you should put comments with the task number and explanation of what to do.
    • Every task has to be done using user function. For example, if the task is to find the sum of a sequence of 5 entered numbers, you must create a function within .cpp file to do this task:
    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
      #include <iostream>
      using namespace std;
       
      int sumSeq() {
      	cout << "enter a sequence"<<endl;
      	int numb;
      	int sum = 0;
      	for (int i = 0; i < 5; i++) {
      		cin >> numb;
      		sum += numb;
      	}
      	return sum;
      }
      void main(){
      	int result = sumSeq();
      	cout << result;
      	system("pause");
      }
    • Try to pass arguments of the functions by reference (in the tasks where it is needed).
    Passing parameters by reference:
    For loop:
    Task 1:
    To do: Create a function to output the sequence: -3 0 3 6 9 12 15 18 21 24. Make the task with FOR loop. An iterator of the loop has a step equaled 3.

    Note 1: To make a step equal to 3 see syntax:

    for ([initializers]; [condition]; [iterator]) 

    instead of the iterator you’ll have the variable counter +=3
    Note 2: The signature of the function must be void printSeq(int & a, int & b), where a = -3 and b = 24.
    Expected output:

    The sequence: -3 0 3 6 9 12 15 18 21 24

    [Solution and Project name: Lesson_3, file name L3Task1main.cpp]

    Task 2:

    To do: 10 integers are input. Create a function (findPosNeg) to output the quantity of positive and negative among them.

    Note 1: Create for loop to input the numbers. Within the loop, check each number whether it is positive or negative. Use two counters to find the quantity.
    Note 2: The signature of the function must be:

    void findPosNeg(int & pos, int & neg){
      //TODO
    }

    Expected output:

    the sequence:
    1  -5  -12   2   3   9   -1  9   5   -8    
    counter_positive = 6, counter_negative = 4

    [Solution and Project name: Lesson_3, file name L3Task2main.cpp]

    Task 3:

    To do: Create a function to calculate the addition of 10 numbers of the sequence: 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 (numbers are NOT input, they must be created using a loop).

    Note: To calculate the addition, use a variable named sum.

    Expected output:

    the sequence:
    1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19   
    sum = 100
    

    [Solution and Project name: Lesson_3, file name L3Task3main.cpp]

    Task 4:

    To do: For every x changing in the interval [x1;x2] (x1 and x2 values are entered), calculate the value of the function z(x,y) = xy. The variable y changes in the interval [y1;y2] (y1 and y2 values are entered). You must create a function.
    Note 1: Create two for loops (nested loop): one loop within the other. Variable x has to be modified in the outer loop; variable y has to be modified in the inner loop.
    Note 2: To output the power of a number, use pow function and #include directive: f = pow(base number, exponent);

    Expected output:

    enter x1 and x2:
    >>>2 >>>8
    enter y1 and y2:
    >>>2 >>>4
    z(x,y) = 2^2 = 4
    z(x,y) = 2^3 = 8
    z(x,y) = 2^4 = 16
    z(x,y) = 3^2 = 9
    z(x,y) = 3^3 = 27
    z(x,y) = 3^4 = 81
    z(x,y) = 4^2 = 16
    z(x,y) = 4^3 = 64
    z(x,y) = 4^4 = 256
    z(x,y) = 5^2 = 25
    z(x,y) = 5^3 = 125
    z(x,y) = 5^4 = 625
    ... etc.

    [Solution and Project name: Lesson_3, file name L3Task4main.cpp]

    While loop:
    Task 5:

    To do: Create a function to output the sequence 15 12 9 6 3 0 (from 15 down to 0 with a step = -3). Use while loop.

    Note: The signature of the function must be:

    void printSeqTask5(int & a, int & b){}

    Where a = 15 and b = 0

    Expected output:

    the sequence:
    15 12 9 6 3 0
    

    [Solution and Project name: Lesson_3, file name L3Task5main.cpp]

    Task 6:

    To do: Create a function to calculate a multiplication of 2-digit even integers in the interval [10;20] (10 * 12 * 14 * 16 * 18 * 20). Make the task using a while loop.
    Note 1: To calculate a multiplication you should use a variable with the name product. Start with product = 1.

    Note 2: The signature of the function must be:

    void findMult(int & a, int & b){}

    where a = 10 and b = 20

    Expected output:

    10 * 12 * 14 * 16 * 18 * 20  
    the product: 9676800

    [Solution and Project name: Lesson_3, file name L3Task6main.cpp]

    Task 7:

    To do: Two two-digit integers are input. Create a BitwiseSum() function that computes their bitwise sum modulo 10. For example, the bitwise sum of the numbers 34 and 59 is the number 83 (3 + 5 = 8; 4 + 9 = 13; 13%10 = 3). Use while loop.

    Note: The BitwiseSum() method must accept two integers arguments passed by reference.

    Expected output:

    Please enter two two-digit numbers:
    >>> 34   >>> 59
    The bitwise sum of 34 and 59 is: 83

    [Solution and Project name: Lesson_3, file name L3Task7main.cpp]

    Task 8:

    To do: A sequence of integers (entered) is given. The last element of the sequence is 0. Calculate the sum of all positive elements of this sequence and the number of its negative elements. While loop must be used.

    Note 1: In the task, you should use the endless loop with an exit from the middle:

    while (true)
    	{
    		cin >> num;
    		if (num == 0)
    			break;
                    ...
                    // calculalete pos and neg, as it is in the task
                    //
            }

    Note 2: To return two values from the function Use function parameters by reference (&):

    void sumPosCountNeg( int& pos_sum, int& neg) {}

    Expected output:

    Please enter the sequence, the last element is 0:
    >>> 3   5   -1   2  -3   0
    The sum of positive numbers is: 10
    The number of negatives is: 2
    

    [Solution and Project name: Lesson_3, file name L3Task8main.cpp]

    Task 9:

    To do: A sequence of integers (entered) is given. The last element of the sequence is 0. Find the minimum and maximum elements. While loop must be used.

    Note 1: In the task, you should use the endless loop with an exit from the middle:

    while (true)
    	{
    		cin >> num;
    		if (num == 0)
    			break;
                    ...
                    // calculalete min and max, as it is in the task
                    //
            }

    Note 2: To return two values from the function Use function parameters by reference (&):

    void minMax( int& min, int& max) {}

    Expected output:

    Please enter the sequence, the last element is 0:
    >>> 3   5   -1   2  -3   0
    The minimum is: -3
    The maximum is: 5
    

    [Solution and Project name: Lesson_3, file name L3Task9main.cpp]

    EXTRA TASKS

    ExtraTask 1 (for loop):

    The Pell numbers PN are given recursively:

    P0 = 0, P1 = 1, PN = 2 PN – 1 + PN – 2

    To do: Create a function to calculate the N-th Pell number (N ≥ 0). Be sure to check that for large N the expression (PN – 1 + PN) / PN is close enough to √2.

    Note: Do not use recursion.

    Expected output:

    Please enter n: 
    >>> 5
    Pell = 70

    [Solution and Project name: Lesson_3, file name L3ExTask1.cpp]

    ExtraTask 2 (while loop):

    To do: An integer is given. Find the number of its digits and their sum.

    Note: The function signature should look like this:

    void digitsCountAndSum (int n, int& count, int& sum)

    Expected output:

    Enter number: 
    >>> 12345
    The number of digits = 5, the sum = 15

    [Solution and Project name: Lesson_3, file name L3ExTask2.cpp]

    ExtraTask 3:

    To do: An integer is given. Generate a new number, the odd (in order) digits of which coincide with the corresponding digits of the original number, and the even ones are equal to zero.

    Note: Create a function with an argument passed by reference.

    Expected output:

    Enter an integer, please: 
    >>> 3627
    Result: 3020

    [Solution and Project name: Lesson_3, file name L3ExTask3.cpp]

    ExtraTask 4 (passing parameters by reference):

    To do: An integer N and a set of N positive real numbers are given. Calculate the sum of all integer parts, as well as the sum of all fractional parts of the sequence. Some of the standard header functions may be helpful.

    Expected output:

    Enter N: 
    >>> 4
    12,4  11,7  8,5  1,1
    Sum of integer parts is: 32 
    Sum of fractional parts is: 1.7

    [Solution and Project name: Lesson_3, file name L3ExTask4.cpp]

    Hometasks

    For loop
    Hometask1:

    To do: 10 integers are input. Create a function to output the addition (sum) of entered numbers.

    Note: Create for loop to input the numbers. To calculate the addition, use a variable named sum.

    Expected output:

    1  -5  -12   2   3   9   -1  9   5   -8   
    sum = 3

    [Solution and Project name: Lesson_3, file name L3HomeTask1.cpp]

    Hometask2:

    To do: 10 real numbers are input. Create a function to output the multiplication of the entered numbers.
    Note 1: Create for loop to input the numbers. To calculate the multiplication, use a variable named product.
    Note 2: Don’t forget to initialize the product variable with a double type value.

    double product = 1.0; 

    Expected output:

    1,1  2,4  5,1  7,2  6,4  8,1  6,7  3,2  3,3  2,4  
    product = 853338,921998746

    [Solution and Project name: Lesson_3, file name L3HomeTask2.cpp]

    Hometask3:

    To do: For every x changing in the interval [30;33], calculate the value of the function z(x,y) = x - y. The variable y changes in the interval [1;5]. You must create a function.

    Note: Create two for loops (nested loop): one loop within the other. The variable x has to be modified in the outer loop; the variable y has to be modified in the inner loop.

    Expected output:

    z(x,y) = 30-1=29
    z(x,y) = 30-2=28
    z(x,y) = 30-3=27
    z(x,y) = 30-4=26
    z(x,y) = 30-5=25
    z(x,y) = 31-1=30
    ... etc.

    [Solution and Project name: Lesson_3, file name L3HomeTask3.cpp]

    While loop
    Hometask4:

    To do: Create a function to output the sequence 3 5 7 9 ... 21 (from 3 to 21 with a step = 2).

    Note: the signature of the function must be void seq(int & a, int & b), where a = 3 and b = 21.

    Expected output:

    3 5 7 9 11 13 15 17 19 21

    [Solution and Project name: Lesson_3, file name L3HomeTask4.cpp]

    Hometask5:

    To do: 5 real numbers are input. Create a function to calculate an addition (sum) of entered numbers. Make the task using a while loop.

    Note: Double type must be used for real numbers and for variable sum:

    double sum = 0;
    double numb;

    Please enter 5 numbers and press Enter

    1.1 4.2 2.1 9.3 2.5
    The sum of inputted numbers = 19.2

    [Solution and Project name: Lesson_3, file name L3HomeTask5.cpp]

    Lesson # 2. C++ Methods / Functions. Multi-file layout

    Theory

    Encapsulation

    In C++, data and functionality are separated into two separate protections: public and private.
    The protection level determines the access that “client code” has to the member data or functionality:

    • Public members can be accessed by client code.
    • Private members cannot be accessed by client code (only used within the functions themselves).

    In C++, the interface (.h file) to the function is defined separately from the implementation (.cpp file).

    Multi-file layout

    To make an application, you usually need to create 3 files: header file (.h), implementation file (.cpp), and main file (.cpp).

    • A header file (.h) defines the interface to functions, that is declaration(s) of the function(s)
    • Implementation .cpp file contains all of the logic of the functions or methods. Header .h file must be included here.
    • Main .cpp file contains of the main function, the starting point of all C++ programs, and here header .h file also need to be included.

    Let’s look at the example of 3 files of single application.
    Sample header file (tasks.h):

    #ifndef TASKS_H
    #define TASKS_H
    //calculates a triangle perimeter 
    double perimeter(double, double, double);
    #endif TASKS_H

    Sample implementation file (.cpp):

    #include "tasks.h"
    //calculates a triangle perimeter 
    double perimeter(double a, double b, double c)
    {
    	//TODO
    }

    Sample main file (.cpp):

    #include <iostream>
    #include "tasks.h"
    using namespace std;
    void main()
    {
    	//prompt user to enter data 
    	//call the function
    	//print out the result
    	system("pause");
    }
  • The.cpp files make requests to include various header files.
  • Then, the cpp file with all of its extra included content will be compiled into object file. (a file has a .o extension, that is an object file.) Each cpp file is separately compiled into an object file.
  • Labs and Tasks

    Lab 1:

    To do: Create an application to find the volume and surface area of a cube. The length of the cube side is given.
    Note: Three solutions must be presented: 1) Without using functions and multi-file application, 2) Using functions, 3) Creating a multi-file application.

    The resulting example:

    Please enter the cube side length: 3.48
    Volume: 42.1442
    Surface area: 72.6624

    [Solution and Project name: Lesson_2Lab1, files’ names HeaderL2Lab1.h, ImpL2Lab1.cpp, MainL2Lab1.cpp]

    ✍ How to do:

    1. Open Microsoft Visual Studio. Select menu item File -> New project. In the Template region find C++ and then, Win32 Console Application.
    2. Create a new console project, name your project Lesson_2Lab1. Among the Additional options mark Empty project and nothing more must be marked. Click Finish button.
    3. In the Solution Explorer window find a Source files folder, click the right mouse button on it and select Add -> New Item. We’re going to create two .cpp files. Call them ImpL2Lab1.cpp – implementation file and MainL2Lab1.cpp – file with a main function.
    4. Now, find a Header files folder, click the right mouse button on it and select Add -> New Item. We’re going to create .h file, and give it a name HeaderL2Lab1.h.
    5.   
      1) Without using functions and multi-file application:

    6. First, we’re going to make this task without functions and encapsulation. So, we should set the cube side length value, and calculate the cube volume and surface area.
    7. Declare a variable of type double for length and set a value for it. Don’t forget to include iostream header, since we’re going to read/write to the console:
    8. #include 
      int main() {
      double length;
      	std::cout << "please enter the cube side length: ";
      	std::cin >> length;
      	// …
      }
      
    9. To prevent console window from closing, you should use pause. The main function must return 0:
    10. //…
         system("pause");
          return 0;
      }
      
    11. Declare variables for the cube volume and surface area. Calculate the values for them:
    12. 	double volume = length * length * length;
      	double surfaceArea = 6 * length * length;
      
    13. After, you can print out the result to the console:
    14.    std::cout << "Volume: " << volume << std::endl;
         std::cout << "Surface area: " << surfaceArea << std::endl;
      
    15. Run the application and check the output.
    16.  
      2) Using functions:

    17. We’re going to modify our application creating methods to calculate the values of volume and surface area.
    18. Find the lines with the variables declarations and calculations and comment them out:
    19. //double volume = length * length * length;
      //double surfaceArea = 6 * length * length;
      
    20. Let’s create a method named getVolume to calculate a cube volume. It must be of double type, since the cube side length is also of double type. Before the method signature you should define the method. You must add the code before the main function:
    21. double getVolume(double length);
      double getVolume(double length)
      {
      	return length * length * length;
      }
      int main() {
          //…
      
    22. Place the declaration of the length inside the main function:
    23. int main() {
      	double length;
      
    24. Create a method named getSurfaceArea to calculate a cube surface area. It must be of double type too. Place the code before the main function:
    25. double getSurfaceArea(double length);
      double getSurfaceArea(double length) {
      	return 6 * length * length;
      }
      
    26. The compiler doesn’t run functions until we call them. Therefore, you must call your methods. Now you can use the variables to store the function returning results. Place the code inside the main function:
    27. double volume = getVolume(length);
      double surfaceArea = getSurfaceArea(length);
      
    28. Run the application and check the output. The results must be as they were.
    29. 3) Creating a multi-file application

    30. We’re going to modify our application creating a multi-file one.
    31. In the Solution Explorer window select (mouse double click) the header file you created (HeaderL2Lab1.h). Inside the code editor window, you must add your method declarations only (you can cut them from your main file and paste here):
    32. #pragma once
      // calculates a cube volume
      double getVolume(double length);
      // calculates a cube surface area
      double getSurfaceArea(double length);
      
      — Notice in this .h file we have not defined how getVolume works, how getSurfaceArea works. All we’ve done is declare that these are the functionalities of our program. We need to look at our .cpp file to find out how they actually work.
      — This pragma once line instructs the compiler to only compile this code once. Even if multiple people use our class, we’ll only want the definition of our methods to be defined exactly once.
      — Note that you should always place the comments before each function.
    33. In the Solution Explorer window select (mouse double click) the implementation file you created (ImpL2Lab1.cpp). Inside the code editor window, you must add your method functionalities (cut them from the main file and paste here). And don’t forget to include the header file first:
    34. #include "HeaderL2Lab1.h"
      double getVolume(double length)
      {
      	return length * length * length;
      }
      double getSurfaceArea(double length) {
      	return 6 * length * length;
      }
      
      — We call this file the implementation file and it’s the code that contains all of the logic to implement our methods.
      — We have a pound (#) include that includes a reference to our header.
      — We have the implementation of our two functions that were defined in our .h file.
    35. Now, we can go ahead and clear up the parts of a code we don’t need anymore within the main function. So, this is what you have in your MainL2Lab1.cpp:
    36. #include 
      #include " HeaderL2Lab1.h"
      int main(){
      	double length;
      	std::cout << "please enter the cube side length: ";
      	std::cin >> length;
              //double volume = length * length * length;
      	//double surfaceArea = 6 * length * length;
      	double volume = getVolume(length);
      	double surfaceArea = getSurfaceArea(length);
      	std::cout << "Volume: " << volume << std::endl;
      	std::cout << "Surface area: " << surfaceArea << std::endl;
      	system("pause");
      	return 0;
      }
      
    37. Run the application and check the output. The results must be as they were.
    38. Three files must be uploaded to the moodle system: HeaderL2Lab1.h, ImpL2Lab1.cpp, MainL2Lab1.cpp.

    Notes on all tasks

  • You can make not all the tasks. Choose some of them to earn enough points.
  • To make the following tasks you’ll need 3 files: tasks.h, tasks.cpp, main.cpp. Download them and place them into the Lesson_2Lab1 folder.
  • When all the tasks you intended to do have been completed, upload those three files to the moodle.
  • [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 0:

    To do: Create a Sum() method that takes two integer arguments and sums them. The method returns the result of integer type.

    Note: You need to create the method declaration in the tasks.h file by yourself, and also the method implementation must be written in the tasks.cpp file. Call the function within the main.cpp. Don’t forget to use the comments to explain the purpose of the method.

    The resulting examples:

    Please, enter two numbers
    20 40 
    The sum of 20 and 40 is: 60
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 1:

    To do: Ask user to enter the lengths of the three sides of the triangle. Create a method named perimeter that calculates the perimeter of a triangle from the lengths of its three sides.

    Note: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    The resulting example:

    please enter three numbers - a triangle three sides: 3.0  4.1  5.0
    perimeter is: 12.1
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 2:

    To do: Ask user to enter the lengths of the three sides of the triangle. Create a method named areaFromSides that calculates the area of a triangle by the lengths of its three sides using Heron’s formula:

    where p stands for semi-perimeter.

    Note 1: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    Note 2: To calculate a square root the math libtary is needed:

    #include <cmath>

    The resulting example:

    please enter three numbers - a triangle three sides: 
    area is: 
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 3:

    To do: Ask user to enter the coordinates of triangle vertices. Create a method named areaFromPos that calculates the area of a triangle using the coordinates of its vertices.

    Note 1: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    Note 2: The math libtary is needed:

    #include <cmath>

    The resulting example:

    please enter six numbers - the coordinates of triangle vertices: 
    area is: 
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 4:

    To do: Ask user to enter the coordinates of two points. Create a function named dist that calculates the distance between two points on the plane, using their coordinates. [sqrt].

    Note: Formula to calculate the distance between two points:

    Note: To check to see if your result is right you can calculate the distance in the wolframalpha service. For example, to find the distance between points (1, -2) and (4, 2), use command distance ({1, -2}, {4, 2}).

    Note: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    The resulting example:

    Please enter the coordinates of two points (four integers: x1, y1, x2, y2):
    1 -2  4  2
    The distance is: 5
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 5:

    To do: Create GetPow() method that takes two integer arguments, they are base number and power number. The method returns the result of taking a base number to power number.

    Note: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    The resulting example:

    Please enter two numbers – a base number and a power number:
    2  4 
    Base number 2 raised to the power number 4 = 16
    

    [Solution and Project name: Lesson_2Lab1, files’ names tasks.h, tasks.cpp, main.cpp]

    Task 6: while loop

    To do: Ask user to enter a number. Create a function named floorCubicRoot that finds the largest integer that does not exceed the cube root of a given number. [pow, floor].

    Note: To check to see if your result is right you can calculate the cube root of the number x in the wolframalpha service using the request x ^ (1/3), for example: 15.625 ^ (1/3) (the answer is 2.5).

    Note: You can use the standard function to calculate the power (pow). But you need to include a math library:

    #include <cmath>

    Note: Three files must be used to complete the task. Check the code of the files and fill in the places marked as // TODO related to this task.

    The resulting example:

    please enter a number: 
    the largest integer is: 
    

    Lesson # 1. Creating a C ++ Console App in Microsoft Visual Studio

    Theory

    Types

    • C++ is a strongly typed programming language where every variable has a type, name, value, and location in memory.
    • In C++, there are only two types of variables that we can have. Every variable is either a primitive variable or it is a user-defined variable.
    • The type of a variable defines the contents of the variable. Every type is either:

    • Primitive
    • User-defined
    • Primitive Types
      There are just 6 common primitive types in C++:

    • int, (4) stores integers
    • char, (1)stores single characters/single byte
    • bool, (1) stores a Boolean (true or false)
    • float, (4) stores a floating point number
    • double, (8)stores a double-precision floating point number
    • void, denotes the absence of a value
    • and some more:

    • short int (2) // или short
    • unsigned int (4) // или unsigned
    • unsigned char (1) // это byte
    • User-Defined Types
      An unbounded number of user-defined types can exist
      Two very common user-defined types:

    • std::string, a string (sequence of characters)
    • std::vector, a dynamically-growing array

    C++ Programs

    Every C++ program must contain a starting point. By the C++ standard, the starting point is a function: int main()
    By convention, the return value of main is 0 (zero) if the program was successful and non-zero on errors.
    Sample:

    int main() {
      int i= 4;
      i = i+ 2;
      char c = 'a';
      std::cout << i << " " << c << std::endl; // output
      return 0;
    }

    C++’s Standard Library (std)

    The C++ standard library (std) provides a set of commonly used functionality and data structures.
    The C++ standard library is organized into many separate sub-libraries that can be #include’d in any C++ program.
    The iostream header includes operations for reading/writing to files and the console itself, including std::cout.

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

    All functionality used from the standard library will be part of the std namespace. Namespaces allow us to avoid name conflicts for commonly used names. If a feature from a namespace is used often, it can be imported into the global space with using statement:

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

    or importing the namespace std itself:

    #include <iostream>
    using namespace std:
    int main() {
    	cout << "Hello, world!" << endl;
    	system("pause");
            return 0;
    }

    C++ SYNTAX

    Initialization in a style of C++11
    double d { 3.14 };
    auto s { "C++" };
    int i { 3.7 }; // error!
    char c { 128 }; // error!
    bool b { -1 }; // error!
    int j { true }; // OK, j == 1
    Arithmetic operations
    a += 2; // a = a+2;
    b = a++; // t = a; a++; b = t;
    b = ++a; // a++; b = a;
    7 / 3 // 7 div 3
    7 % 3 // 7 mod 3
    (i < 0 || i > 2) // OR
    (i >= 2 && i <= 3) // AND
    !(i>2) // не
    & | ^ ~ // bitwise and, or, xor, not
    a = b = c; // multiple assignment

    Block Scope

    The idea is that certain blocks of code, signified by { }, create an inner stack on top of the previous stack memory, which can hide the pre-existing values. The lifetime of stack variables inside a block is called the variable’s scope. Variables created on the stack inside the inner block are only in existence for the duration of the block. When the block ends, the inner stack is removed, and the pre-existing values in the outer scope are available again.

    #include <iostream>
    int main() {
      // In the initial, outer scope:
      int x = 2;
      std::cout << "Outer scope value of x (should be 2): " << x << std::endl;
     
      // Create an inner scope and make a new variable with the name "x".
      // We can redeclare x because of the inner scope.
      {
        int x = 3;
        int y = 4;
        std::cout << "Inner scope vaue of x (should be 3): " << x << std::endl;
        std::cout << "Inner scope vaue of y (should be 4): " << y << std::endl;
      }
     
      // Now that the inner block has closed, the inner x and y are gone.
      // The original x variable is still on the stack (memory), and it has its old value:
      std::cout << "Outer scope value of x (should be 2): " << x << std::endl;
     
      // We can't refer to y here, because it doesn't exist in this scope at all!
      // If you un-comment this line, there will be a compile error.
      // std::cout << "This line causes an error because y doesn't exist: " << y << std::endl;
     
      return 0;
    }

    Condition statements

    If statement

    Some keywords like if can have a block in { } afterwards, which does create an inner block scope for the duration of the conditional block:

    #include <iostream>
    int main() {
      int x = 2;
      std::cout << "Outer scope value of x (should be 2): " << x << std::endl;
     
      if (true) {
        int x = 3;
        std::cout << "Inner scope vaue of x (should be 3): " << x << std::endl;
      }
     
      std::cout << "Outer scope value of x (should be 2): " << x << std::endl;
     
      return 0;
    }
    If-Else
    if (condition) {
        // true case
    }
    else {
        // false case
    }

    or multiple cases:

    if (condition1) {
     
    }
    else if (condition2) {
     
    }
    else if (condition3) {
     
    }
    else {
        // If none of the other conditions were met...
    }
    Ternary operator or conditional operator

    Syntax:

    [Boolean-valued condition] ? [expression to evaluate if true] : [expression to evaluate if false]
    // Since (5<10) is true, the expression before the colon will be selected, which is 1.
    int x = 5 < 10 ? 1 : 2;
    // Now x is equal to 1
    Switch statement

    Syntax:

    switch (variable to check) {
    	case value1:
    		// to do something 
    		break;
    	case value2:
    		// to do something 
    		break;
    	case value3:
    		// to do something 
    		break;
    	…
     
    	default:
    		// to do something if nothing matches
    	}

    Loops

    There are several kinds of loops in C++ that allow you to process data iteratively.
    for loops
    The for loop is a common loop type that lets you specify an iteration variable (counter), a range for that variable, and an increment instruction. The syntax is:

    for ( declaration ; condition ; increment operation ) { loop body }
    #include <iostream>
    int main() {
     
      // outer scope version of "x"
      int x = -1;
     
      // The for loop lets us declare a variable in the first part of the
      // loop statement, which will belong to the inner block scope:
      for (int x = 0; x <= 2; x++) {
        std::cout << "[Inside the loop] x is now: " << x << std::endl; // 0  ..  1 ..  2
      }
     
      // This version doesn't redeclare x, so it just inherits access to the
      // same x variable from the outer scope. This modifies the outer x directly
      for (x = 0; x <= 2; x++) {
        std::cout << "[Inside the loop] x is now: " << x << std::endl;
      }
     
      return 0;
    }

    while loops
    syntax:

    while ( condition ) { loop body }

    We’ll talk about other loops in a later lesson.

    Labs and tasks

    Lab 1: Console С++ app in Microsoft Visual studio
    To do: Create a simple console application that allows you to enter an integer, increase it by one, and print the result out to the console.

    The resulting example:

    Please enter an integer: 4
    Result: 5
    

    [Solution and Project name: Lesson_1, file name main.cpp]

    ✍ How to do:

    1. Open Microsoft Visual Studio. Select menu item File -> New project. In the Template region find C++ and then, Win32 Console Application.
    2. Create a new console project, name your project Lesson_1. Among the Additional options mark Empty project and nothing more. Click Finish button.
    3. In the Solution Explorer window find a Source files folder, click the right mouse button on it and select Add -> New Item. We’re going to create .cpp file. Call it Main.cpp.
    4. Make sure that the file Main.cpp is active in the Solution Explorer window.
    5. Place your cursor on the first line of the code editor window.
    6. Add a header code:
    7. #include <iostream>
      The iostream header includes operations for reading/writing to files and the console itself
    8. After, type the code of the Main function:
    9. int main() {
      		// …
      }
      The main function is a starting point of C++ program.
    10. Place your cursor after the opening curly brace of the main function and make a new line. Add a declaration of the x variable. It must be integer:
    11. int x;
    12. Ask the user to input a number:
    13. std::cout << "Please enter an integer: ";
      The C++ standard library (std) provides a set of commonly used functionality and data structures to build upon.
    14. Use std library again to input a value to store it in x variable:
    15. ...
       std::cin >> x;
      ...
    16. Enter the code to increase x by 1:
    17. x++;
    18. Print the result out to the console:
    19. std::cout << "Result: " << x << std::endl;
      The endl makes a new line after your code.
    20. The main function commonly must return 0. Add the code line right before the closing curly brace of the main function:
    21. return 0;
    22. Run the application. The console window has disappeared too fast. We can’t see the result.
    23. Add the pause to stay the window opened:
    24. system("pause");
         return 0;
      }
    25. Run the application again.
    26.   
      Importing some features from the std library:

    27. In order not always to print std namespace, we can import some it’s functions to our project. Type the following code at the top of your code, in the header region:
    28. using std::cout;
      using std::cin;
      All functionality used from the standard library will be part of the std namespace.
      If a feature from a namespace is used often, it can be imported into the global space
    29. Now, you can change the code with cout and cin methods by clearing up the std:
    30. cout << "Please enter an integer: ";cin >> x;cout << "Result: " << x << endl;
    31. Run the application again.
    32.  
      Importing std namespace:

    33. But instead of importing some features of std library we can import the std namespace itself. Clear the using lines we’ve added. Place the following code instead of them:
    34.  using namespace std;
    35. Run the project and see the same results.
    Task 1: Std and output
    To do: Create a simple console application that prints a welcome phrase (“Hello world!”) out to the console. Give Lesson_1Task1 name to your application and L1Task1.cpp name to your .cpp file. Use the lab 1 to create a console application and give it a name.
      
    The resulting example:

    Hello world!

    [Solution and Project name: Lesson_1Task1, file name L1Task1.cpp]

    Task 2: If statement

    To do: Ask the user to input a number — a grade mark (1, 2, 3, 4, 5). Check the input and print out the characteristic of the mark to the console window (very_bad — 1, bad — 2, satisfactory — 3, good — 4, excellent — 5). The characteristic should be stored in a string variable.

    Note 1: To use string variable you should include the library:

    #include <string>
    … 
    std::string characteristic;

    Note 2: Use the syntax of multiple if statement:

    if (condition 1) {}
    	else if (condition 2) {}
    	else if (condition 3)
    	{}
    	else
    	{}

    The resulting example:

    What’s your mark?
    2
    The characteristic is bad

    [Solution and Project name: Lesson_1Task2, file name L1Task2.cpp]

    Task 3: Switch statement

    To do: Make the previous task using switch statement.

    The resulting example:

    What’s your mark?
    2
    The characteristic is bad

    [Solution and Project name: Lesson_1Task3, file name L1Task3.cpp]

    Task 4:

    To do: Ask the user to enter a number — coffee size (1=small, 2=medium, 3=large). Output the price (1 — 25 cents, 2 — 50 cents, 3 — 75 cents). Use if statement.

    The resulting examples:

    Coffee sizes: 1=small 2=medium 3=large
    Please enter your selection: 
    2
    The result: Please insert 25 cents
    Coffee sizes: 1=small 2=medium 3=large
    Please enter your selection: 
    5
    The result: Invalid selection. Please select 1, 2, or 3.

    [Solution and Project name: Lesson_1Task4, file name L1Task4.cpp]

    Task 5:

    To do: Ask the user to enter a number — coffee size (1=small, 2=medium, 3=large). Output the price (1 — 25 cents, 2 — 50 cents, 3 — 75 cents). Use switch statement.

    The resulting examples:

    Coffee sizes: 1=small 2=medium 3=large
    Please enter your selection: 
    2
    The result: Please insert 25 cents
    Coffee sizes: 1=small 2=medium 3=large
    Please enter your selection: 
    5
    The result: Invalid selection. Please select 1, 2, or 3.

    [Solution and Project name: Lesson_1Task4, file name L1Task4.cpp]

    Task 6: For loop

    To do: Output the sequence: -3 0 3 6 9 12 15 18 21 24. Make the task with FOR loop. An iterator of the loop has a step equaled 3.

    Note: To make a step equal to 3 see syntax:

    for ([initializers]; [condition]; [iterator])

    instead of the iterator you’ll have the variable counter +=3

    The resulting example:

    The sequence: -3 0 3 6 9 12 15 18 21 24

    [Solution and Project name: Lesson_1Task6, file name L1Task6.cpp]

    Task 7

    To do: Output the sequence: 1 2 3 4 . . . 99 100 99 . . . 3 2 1.

    Note 1: Create two for loops: the first loop 1 2 3 4 . . . 99 100, the second loop 99 . . . 3 2 1 (with a step i— as a counter for the second loop).

    The resulting example:

    The sequence: 1 2 3 4 5 . . . 99 100 99 . . . 4 3 2 1

    [Solution and Project name: Lesson_1Task7, file name L1Task7.cs]

    Task 8

    To do: 10 integers are input. Output the quantity of positive and negative among them.

    Note 1: Create for loop to input the numbers. Within the loop, check each number whether it is positive or negative. Use two counters to find the quantity.

    The resulting example:

    1  -5  -12   2   3   9   -1  9   5   -8   => 
    counter_positive = 6, counter_negative = 4

    [Solution and Project name: Lesson_1Task8, file name L1Task8.cs]

    Task 9: While loop

    To do: Calculate a multiplication of 2-digit even integers in the interval [10;20] (10 * 12 * 14 * 16 * 18 * 20). Make the task using a while loop.

    Note: To calculate a multiplication you should use a variable with the name product. Start with product = 1.

    The resulting example:

    10 * 12 * 14 * 16 * 18 * 20  =  9676800

    [Solution and Project name: Lesson_1Task9, file name L1Task9.cs]

    Task 10

    To do: Output the sequence 15 12 9 6 3 0 (from 15 down to 0 with a step = -3).

    The resulting example:

    15 12 9 6 3 0

    [Solution and Project name: Lesson_1Task10, file name L1Task10.cs]

    Вставить формулу как
    Блок
    Строка
    Дополнительные настройки
    Цвет формулы
    Цвет текста
    #333333
    Используйте LaTeX для набора формулы
    Предпросмотр
    \({}\)
    Формула не набрана
    Вставить