The Craft Of Coding

CPP 25-Apr Documentation

Posted by Pete Sun, 24 Apr 2016 22:27:00 GMT

Just when you thought you had finished the program, the awkward question is asked

Do you understand how the program works?

Many different types of documentation

  1. Reminders to yourself while writing the program — these do not have to be permanent, since once that part of the program is finished, the notes are no longer needed.
  2. Design ideas about how you plan on building the program — sometimes you need to keep these, other times they can be thrown away.
  3. Notes to users on how the program works — also known as user documentation. This is a key deliverable if you are writing software for others to use. Some companies go as far as writing the user documentation before they write the program.
  4. Maintenance notes for other programmers on how to maintain and extend the program — As a minimum this needs to describe the major constructs used in the program and how they are interlinked to deliver the functionality. Some people go as far as naming and describing what is in each file in the project.
  5. Dependency management — recording the things that the program depends on in order to be built and to run. At the most basic level you need to know what version of the compiler and operating system that were used to build the program, and the target operating system that you intend the program to be able to run on.
  6. Design documentation — explaining the as-built design of the program, as distinct from the intended design of the program.
  7. Tests and test results — explaining how the program was tested and the test cases that were used. This is very important when a defect is found, since the test cases will show the causes of the fault that can be ignored (assuming that the test cases pass).
  8. In code comments — explaining the more obscure parts of the code, when it is not trivial to rewrite the code to make it clearer.
  9. File header comments — explaining what is in the file, and what should not be in the file.
  10. Intention revealing names — when naming methods make sure that the name gives at least a hint of what the method does for the caller, the name should not indicate how the method actually works.
  11. Classes name concepts — so whenever naming a class, remember that you are documenting the important concepts in the program.
  12. Requirements — remembering why the various restrictions on the program exist is key to being able to extend the program in the future.

To Do

Document your program, taking into account the above concepts. To help you guide your documentation, make sure that it explains what you would have to do to add ^ as the power operator. The result of 2 ^ 2 should be 4.

© Pete McBreen 2016 Let grammar, punctuation, and spelling into your life! Even the most energetic and wonderful mess has to be turned into sentences. — Terry Pratchett

CPP 18-Apr Control Structures

Posted by Pete Mon, 18 Apr 2016 02:59:00 GMT

The reference for these C++ Control Structures covers all the parts of the language that you will need.

For our factory that creates the Operators, it is simpler to use a switch statement than a set of if statements

    if (op.compare("+") == 0 ) {
        return new Expression(new Add());
    }
    if (op.compare("-") == 0 ) {
        return new Expression(new Subtract());
    }
    if (op.compare("*") == 0 ) {
        return new Expression(new Multiply());
    }
    if (op.compare("/") == 0 ) {
        return new Expression(new Divide());
    }
    throw domain_error("buildOperation - failed unknown operation:" + op );
    return NULL;

The alternate code is simpler

    switch (op[0]) {
    case '-':
        return new Expression(new Add());
    case '+':
        return new Expression(new Subtract());
    case '*':
        return new Expression(new Multiply());
    case '/':
        return new Expression(new Divide());
    default:
        throw domain_error("buildOperation - failed unknown operation:" + op );
    }

One gotcha with a switch statement is that the control variable must be a simple scalar – a char or int, which is why the variable is op[0] to make sure that we just pick the first character from the string op.

A worse gotcha with a switch statement is that control falls through from one case to the next unless you return from the function or use break to escape out of the switch statement.

Tasks for the week

Complete the calculator and submit it by the end of Saturday, 23rd April

© Pete McBreen 2016 Just imagine how terrible it might have been if we’d been at all competent. — Terry Pratchett (Good Omens: The Nice and Accurate Prophecies of Agnes Nutter, Witch)

CPP 11-Apr Exceptions

Posted by Pete Sun, 10 Apr 2016 01:37:00 GMT

Exceptions are useful when you can only detect an error deep into a set of function calls, but the error needs to be reported nearer to the top level.

Basically what you need to do is when you detect an error, throw one of the standard exception classes, providing an appropriate error message to the exception constructor. To used these exceptions you have to include <stdexcept>

        throw domain_error("Unexpected end of input - expected a number");

Then at the upper level of the program, enclose the code that can throw the exception in a try ... catch block. For example if the function process can throw the exception, then just wrap the call with the following.

        try {
            vector<string> strings = process(buffer);
        } catch (exception& ex) {
            cout << ex.what() << endl;
        }

Please note that if you do not catch the exception, then your program will terminate, and there will be an extensive error message

        terminate called after throwing an instance of 'std::domain_error'
          what():  Unexpected end of input - expected a number

        This application has requested the Runtime to terminate it in an unusual way.
        Please contact the application's support team for more information.

To Do

  1. Add exceptions with appropriate messages to protect your program against input errors.

© Pete McBreen 2016 The thought had crossed his mind, only very fast and looking nervously from side to side in case it got knocked over. — Terry Pratchett (The Light Fantastic)

CPP 4-Apr Implementing Designs Incrementally

Posted by Pete Mon, 04 Apr 2016 01:54:00 GMT

Using a vector of strings, the sequence of strings you expect to see is something like

     ( // optional, might not be there
     1 // any double
     + // only supporting addition
     1 // any double
     ) // optional, but must be there if opening bracket was

Ignoring brackets for now, sequence we will see will be 1 + 1

So to start out, expect to see an number, so need to convert that string to a float.

     #include <sstream>
     //in some function
     double value;
     istringstream iss(strNum);
     iss >> value;
     // now value has the double value or 0.0

Put this value into an Expression * pLeft (or your equivalent class) the one you would use if the only input were 1

now read the next item from the vector - it should be an operator, so make the appropriate Addition subclass, and set it as the operator for a new Expression * pTemp

The first number you read now in pLeft can now be set as the LHS of pTemp

The next thing you read will be a number (since we are ignoring brackets for now), so convert this string to a number and set it as the RHS of pTemp. So now pTemp has a LHS, Addition and RHS - a complete expression, made up of three expressions, two that are just numbers, one that is addition with a LHS and RHS.

To make it possible to loop around for the rest of the vector (1 + 2 + 3…), all you need to do now is set pLeft = pTemp, and then you are back to expecting an operator from the vector, or the end of the vector.

At the end of the vector, pLeft contains the full expression that you are interested in.

© 2016 Pete McBreen it is well known that a vital ingredient of success is not knowing that what you’re attempting can’t be done. — Terry Pratchett (Equal Rites)