Lab 01

Doxygen

Read Appendix F

Also some information over required comments in the helpful notes section of my website.

Required comments

From the class text book, pages 44 – 45

Commenting required in each source code file:

1. Initial comment at the top of each file

2. Comment for each class

3. Comment for each method or function

4. Comments in the body of each function elaborating on important / difficult logic

Classes

Each class you create will consist of two files: a header file (.h) and implementation file (.cpp).

Header Files:

Layout:


  #ifndef _UNIQUENAME_
  #define _UNIQUENAME_
  //include statements
  class ClassName
  {
    public:
       //public methods
       
    private:
       //private methods
  };
  #endif

Description:

The header file contains the definition of the class. That is declarations of its functions as well as data it stores.

#ifndef / #define / #endif

These are compiler pre-processors to prevent the header file from being included more than once in the linked program. This is done because C++ cannot handle header files being included more than once.

Essentially, it checks to see if the pre-processor macro named _UNIQUENAME_ has already been defined, i.e. the header file has already been included. If not, then it defines it and brings in the rest of the code until the #endif statement. If it has already been defined, then that indicates that this header file has already been included, and thus, the compiler skips down to the #endif statement without including it again.

Make sure the two _UNIQUENAME_ statements are the same.

include statements

Here you will include the other libraries / header files needed in the class. Do not put ‘using’ statements, such as using namespace std; into a header file, if at all possible. So in a header file, if you are using a string type variable, you will want to declare it as std::string. This applies to all functions and objects in the C++ standard library, including cout, cin, and the various streams. More information on the std library

default constructor

This is a constructor with no arguments or one that gives all the arguments default values. These default values should be defined in the header file and not in the implementation file. Usually, this constructor is used to initialize private variables to standard values.

Note: Don’t forget to place a semicolon (;) after the closing bracket of the class definition!

Also, using const at the end of a function declaration indicates that the function cannot alter the classes data members.

Implementation Files:

Layout:

  
    #include HeaderFileName.h
    //using statements
    
    returnType ClassName::methodName
    {
      //method implementation 
    }
  

Example:

  
    #include "Matrix.h"
    using namespace std;

    double Matrix::determinant( ) const
    {
      //...
    }
  

Description:

The format is fairly straightforward, as long as you remember to include the “Matrix::” part.

Inside a function definition, you can access the functions directly without the use of any prefix. So for example, inside the inverse function, the determinant function of the Matrix class could be called using determinant() instead of Matrix::determinant();.

Operator Overloading

All operator overloading means is that we are redefining methods to work with new data types. The ‘overloading’ indicates that after redefining this method, the same method name can be called to execute multiple actual methods, based on the object it is being called on, and the input parameters of the call.

Simple Example:

the ‘+’ operator, when used with integers, performs arithmetic addition:

  
    7 + 3 //returns 10
  
    // However, when used with strings, 
    // the '+' operator performs concatenation:
  
    "Ben " + "Murphy" //returns "Ben Murphy"
	

So this is a form of polymorphism : The ability of objects belonging to different types to respond to method calls of the same name, each one according to an appropriate type-specific behavior.

C++ Syntax

For these arithmetic operators, we must use a special syntax to indicate to the system that we want to define a method in terms of a symbol (+,-,=, etc).

This syntax is adheres to the following format:

  
    <return_type> operator<symbol_to_overload>
    	
  

Example: If we wanted to redefine the == inside of a Fraction class from lab 1, we could use something like:

  
    bool operator==(const Fraction& rhs) const;

  

Where the first const inside the input arguments indicates that we can’t change the value of rhs while the const at the end indicates that no variables of the Fraction class will be modified.

Matrix Determinant

Given a 2×2 matrix M with the values:

[m0,0, m0,1]

[m1,0, m1,1]

The determinant of M is given as:

m0,0 x m1,1 – m1,0 x m0,1

Example: So given a matrix :

[5 , 6]

[2 , 3]

The determinant would be:

5 × 3 – 2 × 6 = 15 – 12 = 3

For a square matrix larger than 2×2, the determinant can be found using the “expansion using minors and cofactors” method.

Definitions

minor

A minor, Ni,j is the sub-matrix of the original matrix M with the ith row and jth column removed.

cofactor

A cofactor for any element is either the minor or the opposite of the minor, depending on where the element is in the original determinant. If the row and column of the element add up to be an even number, then the cofactor is the same as the minor. If the row and column of the element add up to be an odd number, then the cofactor is the opposite of the minor.

This is a confusing definition, but the formula is not difficult as we will see below.

Expansion Using Minors and Cofactors

1. Pick any row or column in the matrix. It does not matter which row or which column you use, the answer will be the same for any row.

2. Multiply every element in that row or column by its cofactor and add. The result is the determinant.

A simpler formula for this algorithm is:

det(M) = summation [ (-1)i+j mij x Ni,j ]

In this setup, the cofactors are taken care of using the (-1)i+j which multiplies the minor( Ni,j) by one or negative one, depending on the row and column.

When the minors associated with each element are larger than 2×2, then they must be expanded in turn until they are reduced to 2×2 matrices, from which a determinant can be computed.

Example If the original matrix was of size 4×4, then this first expansion would create 4 minors, each of size 3×3. Each 3×3 matrix would then need to be expanded to 3 2×2 matrices. From these 2×2 matrices, a determinant is computed.

Matrix Inverse

With a real number, A, the inverse of A, A-1 is the number such that A x A-1 = 1

With a square matrix A, the inverse of A, A-1 is the matrix such that A x A-1 = identity matrix. (all 0’s except for 1’s on the main diagonal)

For a matrix to have an inverse, its determinant cannot be 0.

Other Notes

Online Matrix Math

check your determinant and inverse calculations here

Passing Command Line Arguments

A very common requirement of an application is that it accepts parameters passed to it on execution. In other words, many programs need some information during ‘startup’ to get going.

In C++, this can be accomplished using a special argument list for your main function. So your main function will be modified to look like this:

  
    int main(int argc, char* argv[])
    {
      //...
    }
  

Here we now give two arguments to main: argc and argv.

argc is an integer that indicates the number of arguments passed to your program. Make note that in C++ the name of your program counts as your first parameter. So argc will always be at least 1.

argv is an array of character pointers, each of which points to one of the arguments that was passed in. Because your program’s name counts as the first parameter, argv[0] will always point to that character array.

So, for example, if you had an application called tester and you executed this application using the following command:

  
    $ tester hey you guys
		
  

the variable argc would automatically be populated with the value 4, as there are 3 parameters given, plus the name of the application. Likewise argv would be an array of size 4. argv[0] = "tester", argv[1] = "hey", argv[2] = "you", argv[3] = "guys".

Command Line Arguments in DDD

In order to debug applications that require command line arguments, you will need to indicate to ddd how to run your application. This can be done in the following steps:

Character Sequences

Good tutorial at the c++ reference site

File Streams

We will be making use of ofstreams and ifstreams for reading and writing to files.

To create a i/ofstream with a particular name, simply pass its name as a parameter to the file stream constructor:


  ifstream in("input.txt");
  

We can use the formatted read / write methods: >> and <<. For formatted input, the stream will be read up until the next white space. This white space can be a space, a tab character, or a newline character:

  
    char command[100];
    ifstream in('input.txt');
    in >> command;  // reads in first word of input.txt to the command variable
  

To utilize the ifstream and ofstream classes, we must include the fstream library.

More information can be found on the reference website