Basics of C/C++ Programming: Difference between revisions

From ICO wiki
Jump to navigationJump to search
Jtominga (talk | contribs)
Jtominga (talk | contribs)
 
(54 intermediate revisions by 2 users not shown)
Line 7: Line 7:
Janno Tomingas: janno.tomingas@itcollege.ee
Janno Tomingas: janno.tomingas@itcollege.ee


== C ==


=== Lectures ===
=== Video recordings of lectures and practices ===


1. Week. Introduction to C and C++
Descending date order.


https://echo360.e-ope.ee/ess/echo/presentation/854d0a23-530c-4b4e-a40a-94b4d613d0a1?ec=true
https://echo360.org.uk/media/c002b483-d428-4249-842a-9e92fdebfce8/public


2. Week. Memory, pointers, datatypes
https://echo360.org.uk/media/7efb0957-f384-4eb1-85ad-dd713fe4d65d/public


https://echo360.e-ope.ee/ess/echo/presentation/4c2fd365-3495-4175-a3cb-14b52a001e9e?ec=true
https://echo360.org.uk/media/bba448ab-8a38-405c-b2a2-5353e227265f/public


3. Week. Runtime, stack, heap (dynamic) memory, linker, declaration + definition
https://echo360.org.uk/media/df9ae848-a582-4ba2-999a-8df18d3132c6/public


https://echo360.e-ope.ee/ess/echo/presentation/a4f70f62-3569-4abc-bf81-638ef9e0da7f?ec=true
https://echo360.org.uk/media/02aa7ba3-4bcc-4ace-b676-fd04b58eeff8/public


4. Week. Stack, heap, pointer, jumps, typedef
https://echo360.org.uk/media/8c1485c5-61f3-4062-851d-916906503fd3/public


https://echo360.e-ope.ee/ess/echo/presentation/8e0deb8d-ffab-4a0a-9456-78428674ccb3?ec=true
https://echo360.org.uk/media/2e7e5c6a-10af-4b8c-8303-2e6e4650a206/public


=== Practices ===
https://echo360.org.uk/media/3917eeef-a127-4338-85e5-207d692504b7/public


====== Practice 1 ======
https://echo360.org.uk/media/54f0ef26-6ef2-4bc7-9637-c3cde6a27aaa/public
Console input/output




1. Write a program, that outputs "Hello, World!"
https://echo360.org.uk/media/e099b072-a8ab-4c4b-9c3e-532715cc2d7e/public


2. Write a program, that asks the user for a number and then writes the number back to the user
https://echo360.org.uk/media/6f39d546-5572-4cda-ad97-e61b968506ff/public


3. Write a simple calculator, that supports addition, subtraction, multiplication and division. The program should ask the user for two numbers and the operation to perform and output the result to the console.
https://echo360.org.uk/media/c02ce02d-9e01-45dd-9f54-3be66a1dc2b2/public


====== Practice 2 ======
https://echo360.org.uk/media/2cb53a4e-f2b7-44b7-9bd6-93d90b26043b/public
Functions, pointers, out variables, function return values as success/error codes


https://echo360.org.uk/media/d366f877-b4ae-4fcc-a90c-0d433772252a/public


<div class="mw-collapsible mw-collapsed">1. Write a function that adds two integers, outputs the result via an out variable and returns 0 to indicate a successful operation.
https://echo360.org.uk/media/35cd1108-141b-4a1a-8fb2-63e5f3a5b766/public
Hint:
<div class="mw-collapsible-content">
  int add(int a, int b, int* out)
  {
  }
</div>
</div>


https://echo360.org.uk/media/befc74e4-5873-4c34-a65f-84ebd00e3370/public


<div class="mw-collapsible mw-collapsed">2. Write a function that swaps two integers and returns 0 to indicate a successful operation.
https://echo360.org.uk/media/c3a24815-2b5c-4e3c-8649-bebde59784a3/public
Hint:
<div class="mw-collapsible-content">
  int swap(int* a, int* b)
  {
  }
</div>
</div>


=== Code from lectures ===
http://enos.itcollege.ee/~rliiv/


<div class="mw-collapsible mw-collapsed">3. Write a function that reverses a string and returns 0 to indicate a successful operation.
== C ==
Hint:
<div class="mw-collapsible-content">
  int reverse(char* string, size_t length)
  {
  }
</div>
</div>


=== Practices ===


<div class="mw-collapsible mw-collapsed">4. Write a function that sorts an array of ints and returns 0 to indicate a successful operation.
====== Practice 1 ======
Hint:
Console input/output, conditions, loops, pointers, arrays, functions
<div class="mw-collapsible-content">
  int sort(int* string, size_t length)
  {
  }
</div>
</div>


 
====== Practice 2 ======
====== Practice 3 ======
File input/output, dynamic memory allocation, structs, .h/.c files
File input/output, dynamic memory allocation




<div class="mw-collapsible mw-collapsed">1. Write a program that outputs the contents of a text file into the console.
<div class="mw-collapsible mw-collapsed">1. Write a program that outputs the contents of a text file into the console character by character.
Hint:
Additional info:
<div class="mw-collapsible-content">
<div class="mw-collapsible-content">
Always close the file stream after you are done using it.
Always close the file stream after you are done using it.
Line 96: Line 70:
</div>
</div>


2. Write a program that dynamically allocates a small array of ints. Fill the array and print its contents. Free the memory after you're done using it.


<div class="mw-collapsible mw-collapsed">2. Write a program that reads the contents of a text file into a dynamically sized array and outputs the information into a new file.
<div class="mw-collapsible mw-collapsed">3. Write a program that reads the contents of a whole text file into a dynamically sized array of characters (and outputs the information into a new file).
Hint:
Additional info:
<div class="mw-collapsible-content">
<div class="mw-collapsible-content">
Use "fseek", "ftell" and "rewind" to find out how large the buffer should be.
Use "fseek", "ftell" and "rewind" to find out how large the buffer should be.


Make sure you have enough room for a null terminator.
Make sure you have enough room for a null terminator. (You may have to assign it to the end of the array yourself)


Remember to free the allocated memory after calling malloc or calloc.
Remember to free the allocated memory after calling malloc or calloc.
Line 110: Line 85:
</div>
</div>


 
4. Create an implementation of a stack data structure ([https://en.wikipedia.org/wiki/Stack_(abstract_data_type) Stack (abstract data type)]) that uses a dynamically allocated array for storage.
====== Practice 4 ======
Dynamic memory allocation continued, structs, .h/.c files
 
 
1. Create an implementation of a stack data structure ([https://en.wikipedia.org/wiki/Stack_(abstract_data_type) Stack (abstract data type)]) that uses a dynamically allocated array for storage.
* Required functions:
* Required functions:
** init - Initializes stack's variables and allocates required dynamic memory with an initial(default) size,
** init - Initializes stack's variables and allocates required dynamic memory with an initial(default) size,
Line 134: Line 104:
*How should the functions behave when a stack is empty?
*How should the functions behave when a stack is empty?
*How should the functions behave when a stack is full?
*How should the functions behave when a stack is full?
*What will happen if any of the functions are called unexpectedly many times?
*What will happen if any of the functions are called many times or in unexpected order?
</div>
</div>
</div>
</div>
5. Write a program that reads an unknown number of integers (each on a separate line) from a file into the stack you created. After reading the whole file, print out all ints that were read (in reverse order).
====== Practice 3 (first half) ======
insertion sort, sorting structs
1. Implement insertion sort to sort an array of integers in ascending order.
2. Create a struct to hold integral key-value pairs. Modify the insertion sort algorithm to sort an array of these structs instead.


=== Assignment ===
=== Assignment ===
Line 178: Line 157:


== C++ ==
== C++ ==
=== Lectures C++ ===
5, 6, 7 Week. C++, class, namespace, new + delete, reference, libraries, bool.
https://echo360.e-ope.ee/ess/echo/presentation/6b331ce5-dcc9-4bbf-a490-13d40bef2812?ec=true
https://echo360.e-ope.ee/ess/echo/presentation/4c009949-e8b4-43a0-adc0-8ed055baf7b9?ec=true
https://echo360.e-ope.ee/ess/echo/presentation/f994eebc-39c8-4ea8-8056-d358d89b329c?ec=true
8. Week. Const. + Additional leftover from previous lectures.
https://echo360.e-ope.ee/ess/echo/presentation/95e5962a-3d0b-489f-a759-86dd7a29f2ef?ec=true


=== Practices ===
=== Practices ===
====== Practice 3 (second half) ======
C++ console i/o, std::string, std::vector, references, range based for, auto


====== Practice 1 ======
1. Write a Hello, World! program in C++
Console input/output, strings, references, arrays, new/delete
 
 
<div class="mw-collapsible mw-collapsed">1. Write a simple calculator, that takes a simple binary operation (+,-,*,/) as an input and outputs the result to the console on a new line.
Example:
<div class="mw-collapsible-content">
  1 + 2 -> 3
  3 * 8 -> 24
</div>
</div>
 
<div class="mw-collapsible mw-collapsed">2. Write a program that asks the user for several strings and outputs the total numbers of characters entered.
* Ask for the number of strings the user will enter,
* Store all input strings in in an appropriately sized array,
* Use a function to count the total number of characters entered;
Example:
<div class="mw-collapsible-content">
Input:
3
one
two
three
 
Output:
11
</div>
</div>
 
====== Practice 2 ======
Classes, constructors/destructors, member functions, intro to templates, vector
 
 
1. Create a class Rectangle, that:
* Stores the width and height as private member variables,
* Uses a constructor to set width and height,
* Has public member functions to calculate and return the area and circumference of the rectangle;
 
 
2. Create a program that uses std::vector to store several Rectangles and computes the total area of all stored rectangles.
 
 
3. Convert the stack (Practice 4 of C) from C to C++:
* Replace the struct with a class,
* Add member functions,
* Make use of constructors and destructors,
* Adjust member functions to return values on success (and, for the bold, throw on failure),
* Use a class template to describe the datatype stored in the struct;
 
====== Practice 3 ======
Inheritance, dynamic polymorphism, unique_ptr
 
 
1. Create classes Rectangle and Circle, that:
* Store necessary data as private member variables,
* Have a public member function to calculate and return their area;
 
 
2. Create a program, that:
* Creates and stores some Rectangles and Circles,
* Calculates the total area of the shapes;
 
 
3. Create a base class for previously created objects, called Shape:
* Create a public virtual member function area,
* Create a protected member variable to store the number of a Shape's corners in,
* Modify both Rectangle and Circle to inherit Shape and override the virtual function,
* Modify your program to store Shapes in a vector of unique pointers to Shape;
 
[https://wiki.itcollege.ee/index.php/Basics_of_C/C%2B%2B_Programming_Practice_7_Code Sample code]


2. Write a program that performs an addition operation based on user input. A sample input string: "2+2".


4. Add a class Triangle, that inherits from Shape:
3. Write a program that asks the user for his name, stores it in an std::string and outputs the name back to the console window.
* Store the necessary data,
* Create the necessary functions,
* Use all the Shapes in your program;


4. Write a program that asks the user for several strings and stores them in an std::vector. Upon receiving the last string, the program should output all strings in the order they were received.


5. Add a function to calculate the Shapes' circumference.
5. Modify the last program by adding a function to modify a string by reference. Use that function on all input strings.


 
6. Modify the last program to output the strings using a range based for loop. Bind the values to an auto&.
6. (optional) Similarly to the Shapes, create a hierarchy of Animals, that:
* Know their name,
* Can write out the sound they make;
 
Use your Animals in a simple program.


====== Practice 4 ======
====== Practice 4 ======
Overloading, template functions, template classes
file i/o, command line parameters, new/delete, classes, constructors/destructors, smart pointers
 
 
1. Create a new header file:
* Create a function add - int add (int a, int b),
* Create separate implementations of the add function for floats, doubles, and strings,
* Try out the functions;
 
 
2. Template the add function.
 


3. Create a simple templated Queue ([https://en.wikipedia.org/wiki/Queue_(abstract_data_type) Queue (abstract data type)]), that:
1. Read strings from a file into a std::vector<std::string>, then print them out to another file.
* Uses a container to store the items in,
* Has a member function to add items to the queue (enqueue),
* Has a member function to get items from the queue (dequeue);


2. Modify the last program to read two file names from the command line and use these file names for files.


4. Create a template class Accumulator, that:
3. Create a class that logs its creation and destruction via std::cout. Use a custom defined constructor and destructor for that.
* Stores an instance of the templated type as a member variable,
Observe how actions are logged in different scenarios of instance creation and destruction, including smart pointers.
* Sets the initial value of the variable via the constructor,
* Has a member function to add to the stored value,
* Has a member function to retrieve stored value;
You may assume the templated type is not a pointer and has operator+= defined.
 
 
5. (optional, self-research) Create a class Distance, that can be used with the Accumulator:
* Store the value in a member variable,
* Overload operator+= to support addition between two instances of the Distance class,
Additional information on operators and operator overloading can be found at [http://en.cppreference.com/w/cpp/language/operators operator overloading].
 


====== Practice 5 ======
====== Practice 5 ======
Function pointers, lambdas, std::function
dynamic inheritance, (constructor) overloading, simple templates
 
 
1. Create a function that counts the number of odd numbers in a container of ints:
* Implement the function,
* Store the function pointer in a variable,
* Use the function;
 
 
2. Create a lambda that returns the position of the first negative number in a container of ints:
* Implement the lambda,
* Store the lambda in a variable,
* Use the lambda;
 
 
3. Create a lambda that calculates the factorial of an int:
* Implement the lambda capturing the number by value,
* Use the lambda;
 
 
4. Create a lambda that adds all non-negative numbers in a previously defined container of ints:
* Implement the lambda capturing the container by reference,
* Use the lambda;
 


5. Create a function zero_if, that:
1. Dynamic inheritance
* Takes a reference to container of ints as its first argument,
* Create a base class for several shape types, called Shape with:
* Takes a comparison function as its second argument (has an integer as its parameter and returns a bool),
** virtual default destructor
* Returns void,
** an abstract function that returns the Shape's area
* If the comparison function returns true for an int, sets its value to 0;
** an abstract function that returns the Shape's name
When zeroing all odd numbers in a vector
* Create classes Rectangle and Shape that override the Shape and implement its methods
  [1, 2, 3, 4, 5]
* Use the classes in an std::vector<std::unique_ptr<Shape>> to find the names and areas of several mixed Shapes
The function should return
* Add an overloaded constructor to Rectangle that enables the user to customize the name of some Rectangles
  [0, 2, 0, 4, 0]


2. Exercise
* Create a hierarchy of Animals similarly to the Shapes (with animal names and sounds)
* Provide an overloaded constructor for some Animal


6. Use the created function with newly created lambdas and functions.
3. Simple templates
Sample usage might be to zero all negative integers in a vector.
* Create a Queue of ints, that uses an std::deque as an underlying datatype
* Provide methods to queue and dequeue values
* Convert the Queue to a template class


4. Exercise
* Create an Accumulator of ints
** stores an int as a member variable
** initial value of the accumulator is specified via the constructor
** has a member function that adds a value to the stored value (using the operator +=)
** has a member function that fetches the stored value
* Template the Accumulator to store and add any type of values
* (optional) Create a class Distance that can be used with the Accumulator
** wraps some value (like an int or a double) in a class
** overloads the operator+=


====== Practice 6 ======
====== Practice 6 ======
STL Algorithms, lambdas in use
function pointers, std::function, lambdas, std::algorithm


1. Create a function that counts the number of odd numbers in an std::vector<int>
* Store the function in a function pointer
* Call the function via the function pointer
* Store the function in an std::function
* Call the function via the std::function variable


1. Find the largest element in a container of ints.
2. Re-implement the odd function counter as a lambda
* Store the lambda in an std::function
* Store the lambda in auto
* Call the lambda


2. Sort a vector of ints using:
3. Exercise: Create a lambda that returns the position of the first negative number in a std::vector<int>
* Sort the container into ascending order,
* Provide a custom Compare function to sort the vector into descending order;


4. Lambda capture modes
* Default by value
* Default by reference
* Named by value
** Create a lambda that calculates the factorial of an int that is captured by value
* Named by reference
** Create a lambda that counts the number of negative numbers in an std::vector<int> that is captured by reference


3. From a vector of ints remove all negative values (erase-remove):
5. Create a function zero_if:
* Use std::remove_if to move all elements to be deleted to the end of the vector,
* Takes a reference to a container of ints as its first argument
* Use the vector erase method to delete all the elements from the vector;
* Takes a comparison function as its second argument (std::function<bool(int)>)
* Returns void
* Sets each such value to 0 in the container for which the function returns true


6. std::algorithm (Without looping!)
* Find the largest element in an std::vector<int>
* Sort a vector of ints
** ascending
** descending, using a custom comparer
* Count the number of strings that have a length of over 5 characters in std::vector<std::string>
* Reverse all strings in a std::vector<std::string>


4. From a vector of strings count the number of strings, that have a length greater than 5 characters.
====== Practice 7 ======
std::algorithm continued, nlohmann::json (consuming header only libraries)


[https://www.w3resource.com/JSON/structures.php json structure]


5. From a vector of strings remove all strings that have a length under 3 characters.
1. Create a struct Person that has two fields: a name and an ID number


2. Using std::algorithm
* Find a person by name from a std::vector<Person>
* Find a person by the ID number from a vector<Person>
  vector<Person> people
  {
    Person { 11, "Jack"},
    Person { 43, "John Doe"},
    Person { 42, "Melissa"}
  };
  int idToFind = 43;
  auto location = find_if(begin(people), end(people), [idToFind](Person const& person)
  {
    return person.id == idToFind;
  });
  if (location != end(people))
  {
    // Person found!
    Person found = *location;
  }
* Erase all negative values from a std::vector<int>
** Use std::remove_if to move all elements to be kept to the beginning of vector
** Use std::vector.erase() to erase the unnecessary elements from the end of the vector
  vector<int> ints{ -1, 2, -3, 4, -5, 6, -7, 8 };
  auto firstToRemove = remove_if(begin(ints), end(ints), [](int value)
  {
    return value < 0;
  });
  ints.erase(firstToRemove, end(ints));
* Remove all people whose name is longer than 4 characters and whose ID is odd from an std::vector<Person>
  // Remove people whose id is odd and name longer than 4 characters
  auto lambda = [](Person const& person)
  {
    return person.id % 2 == 1 && person.name.length() > 4;
  };


6. Reverse all strings in a vector of strings.


3. Consuming header only libraries (the simplest way)
* Download the necessary header file
* Move the header file to a well-known folder (project folder, some subfolder, etc)
* #include the header file by specifying a relative path to the header


====== Practice 7 ======
4. Using the nlohmann::json library
Using external libraries
* Open a .json file and read it into a nlohmann::json object in memory
* Open a json file that contains some simple data (int, string, bool, array of ints)
** Read an integer from the json into an int
** Read a string from the json into an std::string
** Read a boolean from the json into a bool
** Read an array of ints from the json into an std::vector<int>


[https://drive.google.com/open?id=1Hd80rp7kQtOeO7r4avLXPLa2SnLW9BVU simple_data.json]


* Download [http://www.sfml-dev.org/ SFML] and create a new project,
  ifstream simple_file("simple_data.json");
* Set up the include and library directories;
  nlohmann::json simple_json;
  simple_file >> simple_json;
  simple_file.close();
  int integer = simple_json["integer"];
  string str = simple_json["string"];
  bool b = simple_json["boolean"];
  vector<int> manyInts = simple_json["ints"];


  // Another way
  int integer2 = simple_json.at("integer").get<int>();
* Open a json file that contains a single item with two integral values ("width" and "height")
** Read the object from the json into a struct Rectangle { int width; int height; }


1. Create an empty window and an initial game loop.
[https://drive.google.com/open?id=1DUKCKLRabTcJ6d2_JpCj-v-o8vU88w60 rectangle.json]


  struct Rectangle
  {
    int width;
    int height;
  };
  void from_json(const nlohmann::json& j, Rectangle& r) {
    r.width = j.at("width").get<int>();
    r.height = j.at("height").get<int>();
  }


2. Draw a white rectangle somewhere on the window.
  ifstream rectangle_file("rectangle.json");
  nlohmann::json rectangle_json;
  rectangle_file >> rectangle_json;
  rectangle_file.close();
  Rectangle rect = rectangle_json;
* Open a json file that contains an array of items from the previous assignment
** Read the array from the json into an std::vector<Rectangle>




3. Handle keyboard arrow events to move the rectangle around.
[https://drive.google.com/open?id=1e9rNgP6_QPg88NhM5LpEm7i75twWPjB1 rectangles.json]


  ifstream rectangles_file("rectangles.json");
  nlohmann::json rectangles_json;
  rectangles_file >> rectangles_json;
  rectangles_file.close();
  vector<Rectangle> rects = rectangles_json;


Create a simple snake game.
=== Assignment ===
 
==== Pizza Shop: ====
 
4. Simulate the movement of the snake:
* Divide the window in a grid to help with movement and collision detection,
* After each frame, draw a new rectangle to the right from the old one,
* Make it possible to change the "moving" direction with arrow keys,
* Do not let the rectangle leave the screen, have it wrap around to the opposite edge instead;


Write a program that calculates the prices for pizzas and tells the pizza shop owner if they have enough ingredients to fill the order.


5. Add the tail:
* Keep track of how long the snake should be,
* Start with having one rectangle in a container (for example an std::deque),
* Add the new rectangle (see part 4) to the start of the container each turn,
* Remove the last rectangle once the tail grows too long;


You are provided 3 files: [https://drive.google.com/open?id=18RY7Nnynd0LmHa74O2NJ_yzAf6fdIcXz recipes.json], [https://drive.google.com/open?id=1RS4ju4d9FTFkN4IjXWQBmHOx-TAQy_qH ingredients.json] and [https://drive.google.com/open?id=1CjoGQ-luAUoyFGpBHEG_Y8pb1PTu3BGp prices.json]. These are all example files and your code must work with any kind of such file that matches the object syntax.


6. Add collision checking:
Each file contains a list of objects whose schema is defined below.
* Once the first rectangle (head of the snake) overlaps with either food or its tail, perform an action,
* If the head overlaps with tail, end the game,
* If the head overlaps with food, grow the tail;


Prices contains the ids and prices for each price.


7. Add food:
Ingredients contains the names, stock counts (total available quantity) and priceTypes for each ingredient - this is the amount of ingredients available for you during one program run. Ingredient priceType is matched with a Price from prices.json file (match them by their id number).
* At the start of the game, spawn the food at a random unoccupied location on the screen,
* When the snake eats the food, spawn more food;


Recipes contains pizzas with ingredients - these are the same ingredients as in ingredients.json file (match them by their name).


== Exploits ==


====== Practice 1 ======
Your program must read all .json files and provide console input where you can enter a pizza (pizza name) to be made. You can make any number of pizzas (at least until there are enough ingredients left).
Assembly language


Setting up your environment:
==== Program usage: ====
* Create a new empty project,
* Add a main.cpp file,
* Under project "Properties -> C/C++ -> Code Generation" set Security Check to Disable Security Check;


To view disassembly:
1. Console asks for pizza name to be made
* While debugging your program, open the disassembly window at Debug -> Windows -> Disassembly;


2. User enters pizza name


2. Create an integer variable i:
3.a. When the pizza can be made (is made):
* Assign a value to i,
* Add 1 to i,
* Inspect the resulting assembly instructions;


Print to console the total price of the pizza.


3. Using what you have learned:
Ingredients used must be taken off your stock.
* Create an integer variable a,
* Using assembly, assign a value to a,
* Using assembly, add 1 to a,
* Verify, that the resulting value is correct;


3.b. When the pizza cannot be made:


4. Create a character array c to hold 3 characters:
Print out which ingredients are missing and how many.
* Fill in the array one by one,
* Inspect the resulting assembly instructions;


4. --Return to step 1--


5. Using what you have learned:
==== Datatypes (schema): ====
* Create a integer array d to hold 2 ints,
* Using assembly, fill the array with data,
* Verify, that the array is filled with expected values;


===== Pizza: =====


6. Create a simple if:
name - string
* Subtract 1 from int i if i is equal to 2,
* Inspect the resulting assembly instructions;


ingredients - list of strings


7. Using what you have learned:
===== Ingredient: =====
* Create an if conditional, that subtracts 1 from int a if int i and a are equal,
* Verify, that the conditional works as expected;


name - string


====== Practice 2 ======
quantity - integer
Assembly language continued, stack smashing


1. Create a function that takes no arguments
priceType - integer
* Call the function
* Inspect the resulting assembly instructions;


===== Price: =====


2. Using what you have learned:
id - integer
* Call the function using assembly,
* Verify that the function gets called;


price - double


3. Create an add function:
== Exploits ==
* The function should return the result of adding two integers passed in as parameters,
* Call the function and store the result in a variable,
* Inspect the resulting assembly instructions;


=== Lectures ===


4. Using what you have learned:
=== Practices ===
* Create a subtract function,
* Use assembly to call the subtract function with different values and store the result in a variable,
* Verify, that the function call works as expected and that the value gets stored;


=== Assignment ===


5. Create a function that internally holds an array of only one void* and takes a void* as a parameter:
== History ==
* Write over the bounds of the array and observe what happens,
==== [[Basics_of_C/C%2B%2B_Programming 2016]] ====
* Try passing different pointers to the function;

Latest revision as of 23:12, 2 January 2018

Introduction

Lecturers

Rait Liiv: rait.liiv@itcollege.ee

Janno Tomingas: janno.tomingas@itcollege.ee


Video recordings of lectures and practices

Descending date order.

https://echo360.org.uk/media/c002b483-d428-4249-842a-9e92fdebfce8/public

https://echo360.org.uk/media/7efb0957-f384-4eb1-85ad-dd713fe4d65d/public

https://echo360.org.uk/media/bba448ab-8a38-405c-b2a2-5353e227265f/public

https://echo360.org.uk/media/df9ae848-a582-4ba2-999a-8df18d3132c6/public

https://echo360.org.uk/media/02aa7ba3-4bcc-4ace-b676-fd04b58eeff8/public

https://echo360.org.uk/media/8c1485c5-61f3-4062-851d-916906503fd3/public

https://echo360.org.uk/media/2e7e5c6a-10af-4b8c-8303-2e6e4650a206/public

https://echo360.org.uk/media/3917eeef-a127-4338-85e5-207d692504b7/public

https://echo360.org.uk/media/54f0ef26-6ef2-4bc7-9637-c3cde6a27aaa/public


https://echo360.org.uk/media/e099b072-a8ab-4c4b-9c3e-532715cc2d7e/public

https://echo360.org.uk/media/6f39d546-5572-4cda-ad97-e61b968506ff/public

https://echo360.org.uk/media/c02ce02d-9e01-45dd-9f54-3be66a1dc2b2/public

https://echo360.org.uk/media/2cb53a4e-f2b7-44b7-9bd6-93d90b26043b/public

https://echo360.org.uk/media/d366f877-b4ae-4fcc-a90c-0d433772252a/public

https://echo360.org.uk/media/35cd1108-141b-4a1a-8fb2-63e5f3a5b766/public

https://echo360.org.uk/media/befc74e4-5873-4c34-a65f-84ebd00e3370/public

https://echo360.org.uk/media/c3a24815-2b5c-4e3c-8649-bebde59784a3/public

Code from lectures

http://enos.itcollege.ee/~rliiv/

C

Practices

Practice 1

Console input/output, conditions, loops, pointers, arrays, functions

Practice 2

File input/output, dynamic memory allocation, structs, .h/.c files


1. Write a program that outputs the contents of a text file into the console character by character.

Additional info:

Always close the file stream after you are done using it.

Make sure to check for error codes.

2. Write a program that dynamically allocates a small array of ints. Fill the array and print its contents. Free the memory after you're done using it.

3. Write a program that reads the contents of a whole text file into a dynamically sized array of characters (and outputs the information into a new file).

Additional info:

Use "fseek", "ftell" and "rewind" to find out how large the buffer should be.

Make sure you have enough room for a null terminator. (You may have to assign it to the end of the array yourself)

Remember to free the allocated memory after calling malloc or calloc.

Make sure to check for error codes.

4. Create an implementation of a stack data structure (Stack (abstract data type)) that uses a dynamically allocated array for storage.

  • Required functions:
    • init - Initializes stack's variables and allocates required dynamic memory with an initial(default) size,
    • destroy - Frees all allocated memory and optionally resets other stored information for a stack,
    • push - Adds an element to the top of the stack,
    • peek - Gets the top element of the stack,
    • pop - Gets and removes the top element of the stack;


  • Describe the stack struct and functions in a separate .h file,
  • Implement the functions in a corresponding .c file,
  • Test your stack with some operations. Remember to check for edge cases;
Hints:
  • How do you know which element to access?
  • How do you know if an array is full?
  • How should the functions behave when a stack is empty?
  • How should the functions behave when a stack is full?
  • What will happen if any of the functions are called many times or in unexpected order?

5. Write a program that reads an unknown number of integers (each on a separate line) from a file into the stack you created. After reading the whole file, print out all ints that were read (in reverse order).

Practice 3 (first half)

insertion sort, sorting structs

1. Implement insertion sort to sort an array of integers in ascending order.

2. Create a struct to hold integral key-value pairs. Modify the insertion sort algorithm to sort an array of these structs instead.

Assignment

Write a program that reads values from a file and outputs the result to stdout.

Input

Input file's name is "input.txt".

The file contains index-value pairs of integers on a single line. Integers in a pair are separated with a comma (,) and pairs are separated with a semicolon (;).

All indices between 0 and (count_of_pairs - 1) are guaranteed to be present.

The indices are guaranteed to be unique.

The indices are not guaranteed to appear in an ascending order.

Sample input: 1,4;0,2;2,8

Output

The program should output the differences between consecutive values as the index increases.

Output should be printed as a comma separated list of values on a single line to stdout.

For input:

0,1;2,4;1,2

Calculates:

0,1 to 1,2 -> 2 - 1 = 1
1,2 to 2,4 -> 4 - 2 = 2

And outputs:

1,2
Examples
->
0,2 -> 0
1,2;0,1 -> 1
1,4;0,2;2,8 -> 2,4
1,4;0,2;2,-2 -> 2,-6

C++

Practices

Practice 3 (second half)

C++ console i/o, std::string, std::vector, references, range based for, auto

1. Write a Hello, World! program in C++

2. Write a program that performs an addition operation based on user input. A sample input string: "2+2".

3. Write a program that asks the user for his name, stores it in an std::string and outputs the name back to the console window.

4. Write a program that asks the user for several strings and stores them in an std::vector. Upon receiving the last string, the program should output all strings in the order they were received.

5. Modify the last program by adding a function to modify a string by reference. Use that function on all input strings.

6. Modify the last program to output the strings using a range based for loop. Bind the values to an auto&.

Practice 4

file i/o, command line parameters, new/delete, classes, constructors/destructors, smart pointers

1. Read strings from a file into a std::vector<std::string>, then print them out to another file.

2. Modify the last program to read two file names from the command line and use these file names for files.

3. Create a class that logs its creation and destruction via std::cout. Use a custom defined constructor and destructor for that. Observe how actions are logged in different scenarios of instance creation and destruction, including smart pointers.

Practice 5

dynamic inheritance, (constructor) overloading, simple templates

1. Dynamic inheritance

  • Create a base class for several shape types, called Shape with:
    • virtual default destructor
    • an abstract function that returns the Shape's area
    • an abstract function that returns the Shape's name
  • Create classes Rectangle and Shape that override the Shape and implement its methods
  • Use the classes in an std::vector<std::unique_ptr<Shape>> to find the names and areas of several mixed Shapes
  • Add an overloaded constructor to Rectangle that enables the user to customize the name of some Rectangles

2. Exercise

  • Create a hierarchy of Animals similarly to the Shapes (with animal names and sounds)
  • Provide an overloaded constructor for some Animal

3. Simple templates

  • Create a Queue of ints, that uses an std::deque as an underlying datatype
  • Provide methods to queue and dequeue values
  • Convert the Queue to a template class

4. Exercise

  • Create an Accumulator of ints
    • stores an int as a member variable
    • initial value of the accumulator is specified via the constructor
    • has a member function that adds a value to the stored value (using the operator +=)
    • has a member function that fetches the stored value
  • Template the Accumulator to store and add any type of values
  • (optional) Create a class Distance that can be used with the Accumulator
    • wraps some value (like an int or a double) in a class
    • overloads the operator+=
Practice 6

function pointers, std::function, lambdas, std::algorithm

1. Create a function that counts the number of odd numbers in an std::vector<int>

  • Store the function in a function pointer
  • Call the function via the function pointer
  • Store the function in an std::function
  • Call the function via the std::function variable

2. Re-implement the odd function counter as a lambda

  • Store the lambda in an std::function
  • Store the lambda in auto
  • Call the lambda

3. Exercise: Create a lambda that returns the position of the first negative number in a std::vector<int>

4. Lambda capture modes

  • Default by value
  • Default by reference
  • Named by value
    • Create a lambda that calculates the factorial of an int that is captured by value
  • Named by reference
    • Create a lambda that counts the number of negative numbers in an std::vector<int> that is captured by reference

5. Create a function zero_if:

  • Takes a reference to a container of ints as its first argument
  • Takes a comparison function as its second argument (std::function<bool(int)>)
  • Returns void
  • Sets each such value to 0 in the container for which the function returns true

6. std::algorithm (Without looping!)

  • Find the largest element in an std::vector<int>
  • Sort a vector of ints
    • ascending
    • descending, using a custom comparer
  • Count the number of strings that have a length of over 5 characters in std::vector<std::string>
  • Reverse all strings in a std::vector<std::string>
Practice 7

std::algorithm continued, nlohmann::json (consuming header only libraries)

json structure

1. Create a struct Person that has two fields: a name and an ID number

2. Using std::algorithm

  • Find a person by name from a std::vector<Person>
  • Find a person by the ID number from a vector<Person>
 vector<Person> people
 {
   Person { 11, "Jack"},
   Person { 43, "John Doe"},
   Person { 42, "Melissa"}
 };
 int idToFind = 43;
 auto location = find_if(begin(people), end(people), [idToFind](Person const& person)
 {
   return person.id == idToFind;
 });
 if (location != end(people))
 {
   // Person found!
   Person found = *location;
 }
  • Erase all negative values from a std::vector<int>
    • Use std::remove_if to move all elements to be kept to the beginning of vector
    • Use std::vector.erase() to erase the unnecessary elements from the end of the vector
 vector<int> ints{ -1, 2, -3, 4, -5, 6, -7, 8 };
 auto firstToRemove = remove_if(begin(ints), end(ints), [](int value) 
 {
   return value < 0;
 });
 ints.erase(firstToRemove, end(ints));
  • Remove all people whose name is longer than 4 characters and whose ID is odd from an std::vector<Person>
 // Remove people whose id is odd and name longer than 4 characters
 auto lambda = [](Person const& person)
 {
   return person.id % 2 == 1 && person.name.length() > 4;
 };


3. Consuming header only libraries (the simplest way)

  • Download the necessary header file
  • Move the header file to a well-known folder (project folder, some subfolder, etc)
  • #include the header file by specifying a relative path to the header

4. Using the nlohmann::json library

  • Open a .json file and read it into a nlohmann::json object in memory
  • Open a json file that contains some simple data (int, string, bool, array of ints)
    • Read an integer from the json into an int
    • Read a string from the json into an std::string
    • Read a boolean from the json into a bool
    • Read an array of ints from the json into an std::vector<int>

simple_data.json

 ifstream simple_file("simple_data.json");
 nlohmann::json simple_json;
 simple_file >> simple_json;
 simple_file.close();
 int integer = simple_json["integer"];
 string str = simple_json["string"];
 bool b = simple_json["boolean"];
 vector<int> manyInts = simple_json["ints"];
 // Another way
 int integer2 = simple_json.at("integer").get<int>();
  • Open a json file that contains a single item with two integral values ("width" and "height")
    • Read the object from the json into a struct Rectangle { int width; int height; }

rectangle.json

 struct Rectangle
 {
   int width; 
   int height;
 };
 void from_json(const nlohmann::json& j, Rectangle& r) {
   r.width = j.at("width").get<int>();
   r.height = j.at("height").get<int>();
 }
 ifstream rectangle_file("rectangle.json");
 nlohmann::json rectangle_json;
 rectangle_file >> rectangle_json;
 rectangle_file.close();
 Rectangle rect = rectangle_json;
  • Open a json file that contains an array of items from the previous assignment
    • Read the array from the json into an std::vector<Rectangle>


rectangles.json

 ifstream rectangles_file("rectangles.json");
 nlohmann::json rectangles_json;
 rectangles_file >> rectangles_json;
 rectangles_file.close();
 vector<Rectangle> rects = rectangles_json;

Assignment

Pizza Shop:

Write a program that calculates the prices for pizzas and tells the pizza shop owner if they have enough ingredients to fill the order.


You are provided 3 files: recipes.json, ingredients.json and prices.json. These are all example files and your code must work with any kind of such file that matches the object syntax.

Each file contains a list of objects whose schema is defined below.

Prices contains the ids and prices for each price.

Ingredients contains the names, stock counts (total available quantity) and priceTypes for each ingredient - this is the amount of ingredients available for you during one program run. Ingredient priceType is matched with a Price from prices.json file (match them by their id number).

Recipes contains pizzas with ingredients - these are the same ingredients as in ingredients.json file (match them by their name).


Your program must read all .json files and provide console input where you can enter a pizza (pizza name) to be made. You can make any number of pizzas (at least until there are enough ingredients left).

Program usage:

1. Console asks for pizza name to be made

2. User enters pizza name

3.a. When the pizza can be made (is made):

Print to console the total price of the pizza.

Ingredients used must be taken off your stock.

3.b. When the pizza cannot be made:

Print out which ingredients are missing and how many.

4. --Return to step 1--

Datatypes (schema):

Pizza:

name - string

ingredients - list of strings

Ingredient:

name - string

quantity - integer

priceType - integer

Price:

id - integer

price - double

Exploits

Lectures

Practices

Assignment

History

Basics_of_C/C++_Programming 2016