Pointers for the first semester are important for placement

The "Programming II" module takes place in the 2nd semester of the Media Informatics course with a volume of 2/0/2 SWS. Programming knowledge of the C programming language is required.
The course is assessed with the help of two parts, both of which must be passed. A complex software project has to be developed during the semester (APL, receipt, weighting 30%). The task and the assessment criteria will be announced in the course of the course. A written examination takes place during the examination period (120 minutes, weighting 70%).


Content of the course

  • basic extensions to C
    we start with the "non-object-oriented" extensions
  • credentials
    There is more to C ++ than just pointers to values
  • Classes and objects
    now it becomes object-oriented
  • dynamic memory management
    new possibilities related to constructors and destructors
  • a minimal example of an MFC program
    here we work with application and window objects, we handle events
  • Animations with sprites
    Graphic user interfaces should be programmed in an object-oriented manner
  • Inheritance and Polymorphism
    one of the most important pillars of object-oriented programming
  • further object properties
    static elements, "friendships" between classes, class arrays, ...
  • Operator overloading
    the semantics of operators depend on the operands
  • Templates
    we implement classes and only specify the type of some values ​​when the class is used ...
  • Exception handling
    error handling is left to the user of the class
  • Namespaces
    Name conflicts are a thing of the past
  • Complex example
    we will summarize our knowledge once again when programming a small "graphics editor"



Internship tasks:





Basic extensions to C


Exercise 1: Input and output via cin and cout
Create a C ++ program that prompts the user for either the number 1, 2, or the number 3. If you enter the number 1, the program outputs the name of the programmer, if you enter the number 2, it is the address of the programmer and if you enter a 3, its date of birth. The values ​​to be output are to be saved in variables, whereby a numerical variable is to be used for the date of birth. The address is to be output on several lines.

Save the date to an int value (32 bit), using one byte for the day and month and two bytes for the year. Use the << and >> operators to set and read out the values. Make it clear that these operators have now been assigned additional semantics in C ++ with streaming.


Task 2: Formatted output
Write a C ++ program that reads a decimal number from the keyboard and returns the same number to the screen in octal and hexadecimal notation.

Task 3: Standard values ​​for function parameters
Your C ++ program should contain a function that outputs personal data on the screen. The function must be called with at least one parameter (the name of the person). Additional parameters can optionally be specified: age, gender, place of residence and telephone number. If the last parameters are not specified when the call is made, the corresponding line is omitted in the output mask of the function. write ("Albin", 'm', 10); // display name, gender and age write ("Sabine"); // only the name is output write (); // ERROR
Exercise 4: Overloading functions
Write a C ++ program with a multiply overloaded function add. With the help of this function, the addition of integer values, floating point numbers and character strings should be possible. Test your function with the following program lines: cout < "3+4"="">< add(3,4);="" cout="">< "3.1+4.1"="">< add(3.1,4.1);="" char="" a[20]="{"alles"}," b[20]="{"" einfach"};="" cout="">< "alles="" +="" einfach"="">< add(a,b);="" achten="" sie="" bei="" der="" addition="" von="" zeichenketten="" auf="" das="" problem="" des="" bereitstellens="" von="" speicherplatz="" für="" die="" verketteten="" werte.="">




credentials


Exercise 1a: Deleting vector elements
Program a function "delete" with 3 parameters: a vector with int values, the number of vector elements and another int value that specifies the position of the vector element that is to be deleted. The second parameter is to be passed as a reference.

Test your function: Please note that the number of valid vector elements changes after each call. To output the vector on the screen, you also use a self-programmed function that receives the vector and the number of vector elements as parameters. The vector is to be implemented as a "constant pointer" (const).

Exercise 1b: Deleting vector elements in a structure variable
Change the program from the previous exercise as follows:
  • A structure manages the vector and its length.
  • The delete function receives a reference to the structure variable and the position of the element to be deleted as a parameter.
  • The output function works with a constant reference to the structure variable.
  • Additional task: Now try to manage the memory of the vector dynamically :-)
Make it clear to yourself what efficiency gain working with references means at this point. In anticipation: The structure variable you created is already a C ++ object ;-)

Exercise 2: Swap values
Write two functions named swap (see also overloading functions). Both functions have the task of swapping the values ​​of two variables of the type int. Implement this functionality in one swap function with the help of pointers and in the other function with the help of references. Test both functions and see the difference.



Classes and objects



Task 1: Constructors and Destructors
Write a C ++ program with a class INT that contains 3 methods in addition to a data element of type int: a constructor, a destructor and a display function to display the int value. The only parameter of the constructor is the int value to be saved in the object, which it transfers to the data element and also outputs on the screen together with the string "constructor call". The destructor method outputs the int value together with the character string "destructor call" on the screen.

In addition to the declaration and definition of the INT class, your C ++ program also contains the following program lines: void myfunc () {cout < "**="" erste="" anweisung="" in="" myfunc\n"="" ;="" int="" i(10);="" lokal="" static="" int="" j(11);="" lokal="" statisch="" cout="">< "**="" letzte="" anweisung="" in="" myfunc\n"="" ;="" }="" int="" a(0);="" global="" int="" main()="" {="" int="" x(1);="" lokal="" cout="">< "*="" in="" main:="" zum="" ersten="" mal\n";="" myfunc();="" cout="">< "*="" in="" main:="" zum="" zweiten="" mal\n";="" myfunc();="" cout="">< "*="" letzte="" anweisung="" in="" main="" \n";="" return="" 0;="" }="">
Explain the notices of the program you have created!

Extend your INT class by a method with the name "add", which is to add the value transferred as a parameter to the current value of the object: INT o (5); o.add (10); o.display ();
Now overload the add method so that the following call is possible: INT o (5), n (10); o.add (n); o.display (); Add the above examples to your lecture notes.

Exercise 2: the vector class
Write a class CVektor50. Vector objects can be created as instances of this class, each of which can contain up to 50 vector elements of the type int. Every object "knows" how many valid elements its vector currently contains. The following methods should belong to the CVektor50 class:
  • a standard constructor that initializes all vector elements with 0 and sets the vector size to 50.
  • a constructor with a parameter num (type int): The first num values ​​of the vector (num<=50) mit="" zufallszahlen="" initialisiert.="">
  • a method of sorting the vector,
  • a method for inserting and a method for deleting a vector element at a certain point. (Note that this changes the number of valid vector elements.)
  • and a method for displaying the vector content on the screen.
If possible, use the C functions created last semester by adapting them for your new class. Instances of the classes should only be accessible using the methods specified above. Test your new class.

Exercise 3: simple graphics classes
Write one class each to describe the graphic primitives point, circle, line, triangle and square (Cpoint, Ccircle, Cline, Ctriangle, Cquare). The class CPunkt is to be used to implement the classes CLine, C circle, C triangle and C square in the sense of the "used relationship". A display () method should serve to output the properties of an object (this time in text form). All encapsulated properties should be changeable and queryable using methods of the class.

Write a container class CContainer that can "collect" 50 objects of the above-mentioned classes in an array. Methods for inserting and deleting such objects are to be provided. A display () method is used to output all collected objects.



Dynamic memory management


Exercise 1: a vector class with dynamic vector length
change your program from the task "the vector class" of the section "classes and objects" so that the vector size is no longer restricted to a maximum of 50 elements, but is dynamic. So note that the size of the vector changes as you insert and delete elements. The following methods should also be implemented:
  • A destructor (including the release of the memory that was occupied by the object),
  • The constructor creates an "empty" vector with 0 vector elements.
  • overwrite the assignment operator and copy constructor.
Test your program with a small main () function or in a Windows program (you would have to change the output function to do this).

Additional task:
  • A writing method writes the elements of the vector in a binary file (i.e. all int values ​​with each sizeof (int) bytes). Note that you must first write the current number of elements to the file at the beginning of the file. The file name is to be used as a parameter.
  • A read method is used to read binary files that were written using the write method. The vector elements read are appended to the current vector. The file name is to be used as a parameter.
Test your class by creating several object instances at the same time and providing the user (DAU) with the appropriate methods for these objects via a small menu.

Task 2: a dynamic container class for graphic objects
Change your program from the "Simple graphic classes" task in the "Classes and objects" section so that the size of the "container" is no longer limited to 50 graphic objects, but is dynamic. So note that the size of the vector changes as you insert and delete elements. The following methods should also be implemented (although you can of course use the algorithms from the previous exercise again):
  • A destructor (including the release of the memory that was occupied by the object),
  • The constructor creates an "empty" container with 0 objects.
  • overwrite the assignment operator and copy constructor.
Test your program with a small main () function or in a Windows program. Here, too, you can implement suitable methods that can write the container content to a file or read it from a file. So you have the foundation for your first own graphics editor :-)

Task 3: CLineList - for doubly linked lists
Write a class CLineList whose object instance manages a doubly linked list with the following data elements. int element_no; enum color {red, green, blue}; int coord_x1, coord_y1; int coord_x2, coord_y2; First, implement a class C line to encapsulate this data. The class CLinie only has a constructor, a destructor and a display method for displaying the values ​​(in text form or graphically). Think about where to define the list. Now write the class CLineList by converting the C functions for doubly linked lists known from the lecture to methods of your class. Work within the CLineList class with a local CElement class that encapsulates a pointer to the predecessor, the successor and an element of the CLinie class. Such a list is initialized in the standard constructor. In the destructor, the list must be completely emptied and the memory of all elements released again.

Test your class by creating several object instances and using a small menu to provide the user (DAU) with the appropriate methods for these objects.



Windows programming and sprite animation



Task 1: a first dialogue application
Make yourself familiar with the "Microsoft Developer Studio" and the project type "MFC Application". Generate your first dialog application. The dialog window has the heading "First dialog application". Enter the string "Hello world" (or something similar) at coordinates 10,10. Compare the generated classes and objects with the first example in the lecture. Where does the dialogue start?

Task 2: reaction to events
Expand your project from the first task so that you react to mouse events.Use the development environment to insert WM_LBUTTONDBLCLK-, WM_LBUTTONDOWN-, WM_LBUTTONUP-, WM_RBUTTONDBLCLK-, WM_RBUTTONDOWN- and WM_RBUTTONUP event handlers for the mouse events. These output the name of the event on the screen at the mouse position at which the event was triggered. Add an event handler for the WM_MOUSEMOVE event to your program, which outputs the current mouse coordinates at position 10,10 if the mouse was moved with the mouse button held down.

In the middle of the window, type the letter 'x'.

This letter should be able to be moved in the window with the cursor keys. The letter to be displayed can be changed using the WM_CHAR event handler.

What would you have to change so that the output is retained if, for example, the window is to retain its content after being covered?



Task 3: the CDIB class
Generate a dialog-based application with the Visual C ++ development environment. Add 3 buttons to your application and connect them to appropriate event dealers. The buttons are labeled "draw background", "draw sprite", "sprite animation". The event dealers initially only output these character strings on the screen. Test your application. Include the CDIB class in your project and copy the files "snow.bmp" and "dogs.bmp" into the current project directory. Create two member variables of the CDIB class in the dialog class. Load the file "snow.bmp" in the event dealer of the button "draw background" onto one of these member variables and then draw the picture. Test your application.

change your event handler of the button "draw sprite": Load the file "dogs.bmp" on the second member variable of the class CDIB. Use the SpriteAdd method to copy a sprite state of the file into the background image and display the changed CDIB object with the background image in the dialog window. Test your application.

Change your event dealer for the "Sprite animation" button: Draw a sequence of sprite states from the "dogs.bmp" file (as an animation of a running dog) in the dialog window. Use the SpriteAdd method for this as well. Another object of the CDIB class with the background image helps you to reset the CDIB object changed by SpriteAdd to its original state.

Task 4a: Control of sprites with timers, graphic menu guidance
Use Visual C ++ and the Sprite library provided to program a Windows program that moves 3 sprites controlled by a timer as shown in the following screenshot. The "sprite animation" should generate 15 images per second. The horizontally moving sprite moves 4 pixels to the left per image, the other sprite -2.5 pixels in the x-direction and 1.5 pixels in the y-direction. Think about a suitable distribution of the sprites on z-planes. The Sprite files will be made available to you during the internship.



Add three more sprites (from the buttons.bmp file) to control the animation. If the mouse is placed over one of these sprites, this sprite changes its appearance from gray to red and thus shows that it is a sensitive screen area. If the start sprite is clicked with the mouse, the animation starts. The stop sprite stops the animation. The application can be left with Exit.

Exercise 4b: Drag & Drop Sprites
The program from the previous exercise is to be expanded so that the sprites for the individual menu items can be placed anywhere in the dialog window using drag & drop. Use the right mouse button for this.

Exercise 5: an interactive ping pong game
Program a simple game of ping pong. The game consists of 2 clubs, which are located on the left or right edge of the screen and can be moved up and down by moving the mouse. With the help of the bat you have to try to keep a ball within the dialogue window. The ball (a sprite, of course) is reflected from the top and bottom of the dialog box and the clubs. If the ball touches a side edge of the dialog window, the player receives a minus point (displayed in the status line or in the title of the window). Every minute a new ball (of a different color) comes into play. A maximum of 5 balls are to be supported. With the 'A' key your game can be put into an "automatic mode" ;-)

Task 6: An interactive catalog
The functionality of a virtual catalog known from "Quicktime VR" has to be implemented with the sprite library. To do this, use the specifications from the lecture example in a fashion catalog.

The "model prite" reacts to the WM_LBUTTONDOWN event and can then be rotated to the right or left with WM_MOUSEMOVE event sequences until WM_LBUTTONUP occurs.





Inheritance and Polymorphism

Exercise 1: graphic primitives
Write a class CGrafik which has an object m_punkt of class CPoint and an object m_name of class CString as member variable. A constructor is used to initialize these variables. Two classes can be derived from this base class:
  • the class CKreis with a member variable m_diameter and
  • the class CLinie with the member variable m_zweiterpunkt (type CPoint).
The constructor of these classes is used to initialize the member variables and also uses the constructor of the base class. In addition, these two classes have a method display, which draws the respective graphic primitive on the screen (parameterize this method with a device context) and also writes the name m_name to the object. Think about where it makes the most sense to implement the name output.


Test your classes in a simple dialog application that also contains a button labeled "Draw", which creates an object of the classes C line and C circle, initializes it with random coordinates (within the window size) and draws it.

Exercise 2: Base class pointers for graphic primitives
Extend the application from Exercise 1 by a class CEllipse, which also inherits from the class Cgraphic and has a constructor and a method display (). Add a vector for 20 pointers to elements of the Cgraphic class to the dialog class of your application. First initialize this vector with NULL pointers. In the event handler of a new button labeled "new objects", 20 new objects of the classes CLine, Ccircle and Cllipse are randomly generated and their addresses are stored in the vector.
Change the event handler of the "Draw" button so that the display method is executed on all base class pointers stored in the vector. Don't forget to destroy these dynamically created objects again. Is it now clear why the destructor of the Cgraphic class must also be virtual?



Task 3: a class CElemList and its elements
Write yourself a class CElemList that is supposed to provide functionality for singly linked lists and that initially only implements the following methods. The basic functionality known from the lecture for simply linked lists must be implemented in methods. The list stores pointers to objects of the CElement class, which also has to be implemented and provides the purely virtual method display.

class CElemList {private: CElement * anchor; int num; public: CElemList (void); ~ CElemList (void); void insert (CElement * e); void deletefirst (); CString display (); };




You can also program three element classes, which are directly derived from CElement, CIntElement, CFloatElement and CXElement. These classes are used to manage element values ​​of the type int, float and a complex structured data type of your choice with constructor, destructor and display () method.
Now test your classes with different element types. Where did you implement polymorphism?

Comment: You can (and should) continue to work with Windows applications here as well. With Visual Studio it is very easy to place a button in the dialog in the resource editor and then insert an event handler for this button in the dialog class with a "double click". There you can now solve your task and with the method dc.DrawText (...) write the text output on the window with the help of a CString object, e.g. CElemList li; CClientDC dc (this); CFont f; f.CreatePointFont (85, "Courier New"); // new font with 8.5 pt dc.SelectObject (& f); dc.SetBkMode (TRANSPARENT); // dial into the device context CString s ("Initialize list with int and float ... \ n"); for (int i = 10; i> 0; i--) if (i% 2) li.insert (new CIntElement (i)); else li.insert (new CFloatElement ((float) i)); s + = left display (); ... li.insert (new CStringElement ("Hello")); s + = left display (); // compose CString object dc.DrawText (s, CRect (15,50,400,300), DT_LEFT); // and output



Exercise 4: Extension of the CDIB class (1)
Write a class CTileDIB whose base class is the class CDIB you are already familiar with. Override the Draw method of the base class with a Draw method that tiled the contents of the bitmap in a given area (program this method using the inherited method CDIB :: Draw (...) from the base class). The number of "tiles" in the X and Y directions must be transferred as an int parameter, i.e. the declaration of the CTileDIB :: Draw (...) method is the same as the CDIB :: Draw (...) method.

Test your class in a simple dialog application.

Exercise 5: Extension of the CDIB class (2)
Write a class CCenterDIB whose base class is the class CDIB you are already familiar with. Override the Draw method of the base class with a Draw method that draws the bitmap centered in a given area (program this method using the inherited method CDIB :: Draw (...) from the base class). The area to which the centering applies begins at the coordinates 0.0. The width and height of the area are to be passed as int parameters, i.e. the declaration of the CCenterDIB :: Draw (...) method is the same as the CDIB :: Draw (...) method. Test your class in a simple dialog application. The size of the dialog window can be determined using the CWnd :: GetClientRect (CRect *) method.



Operator overloading


Exercise 1: addition of vectors
Change your program for the task "a vector class with dynamic vector length" in the section "dynamic memory management" so that the + operator can be used for addition (i.e. for connecting vectors and adding a new vector element) for objects of this class. Note that to test the overloaded operator, you must also overload the assignment operator and the copy constructor. So that we can use these operators consistently, the + = operator must now be overloaded.

Vector v1 (5), v2 (10), v3; v1.display (); v2.display (); v3 = v1 + v2 + 1000; v3.display (); v3 + = v1; v3.display (); Vector v4 = v1; // copy constructor v4.display ();
By overloading the [] operator, "safe" access to individual vector elements, reading and writing, is to be guaranteed.

cout << "v1 [0] =" << v1 [0] << endl; v1 [0] = 1000; cout << "v1 [0] =" << v1 [0] << endl; Now overload the << operator so that the vector objects can be output using streams.

cout << "The content of the vector v1:" << v1 << endl;

Exercise 2: Operators for graphic primitives
Overload operators for the class CKreis created in the previous internships. The "+" operator adds two circles. The diameter of the result circle results from the sum of the diameters of the two operands. The center of the result circle is in the middle between the circles selected as operands. Test the '+' operator with a small dialog application. Note that to test the overloaded "+" operator, you must also overload the assignment operator and (possibly) the copy constructor.



Exercise 3: Adding lists
Change your program for the task "Class CELemList" in the section "Inheritance and polymorphism" so that the "+" operator can be used to add (i.e. concatenate) list elements for objects of this class. Where do you have to define the operator so that as many classes in your inheritance hierarchy as possible benefit from it?

Beware: this task is not as easy as it seems at first! Because of the dynamic memory management, we still need our own assignment operator and a copy constructor. But how can these operators create copies of objects using base class pointers?



Templates


Task 1: Storage tank and graphic objects
Implement (using the lecture example) a template for the functionality of a storage tank with dynamic storage management. Test this stack with different data types and with the graphic objects introduced above in a dialog application. To do this, generate 10 circles, for example the following coordinates ((100,100), (120,120), (140,140) ...) and a diameter of 100 pixels, which overlap diagonally in the window. These circles are to be drawn and then stored in the basement. If the user clicks on the button ("Auskellern"), you fetch all the circles from the basement one after the other and draw each one after the pop () command. Your application works correctly if the z-positions of the circles have been inverted.






Exception handling


Task 1: Stacking storage with exception handling
Use the template of a cellar from the last internship. To repeat, first overwrite the '=' operator, the '+' operator, the '+ =' operator and the copy constructor.Now implement and test the [] operator for direct access to individual objects in the basement. If the index is incorrect, this operator triggers an exception, which is "caught" in the dialog class and handled (e.g. with a message box).

Task 2: The CMyString class
You will know a class for character strings from the lecture section on dynamic memory management. Implement this class here under the name CMyString. Override the assignment and '+' operators, the default constructor, the copy constructor, and the destructor. Now implement and test the [] operator to access individual characters of the character string. If the index is incorrect, this operator triggers an exception, which is "caught" in the dialog class and handled (e.g. with a message box).