Testing and debugging approaches

Now that we have some advanced control structures to deal with, particularly loops and function calls, it is time to seriously consider organized approaches to testing and debugging source code.

Software testing: producing quality software

One of the most important goals in the development of any software program is that of convincing ourselves and others that the program is trustworthy.

This requires far more than simply showing that the program "works ok" for a few typical input cases.

For all software we want to ensure many things:

This is a very tall order, particularly for large, complex software projects.

There are, however, a number of typical or predictable sources of error in most programs and a number of steps we can take to improve our code quality.

Developing Test Sets


We cannot trust a program unless it has been fully tested, and as developers we are in an ideal position to create strong test sets for a program.

THE GOAL OF TESTING IS TO REVEAL INADEQUACIES IN SOFTWARE

Don't write "cushy" test sets that you're pretty sure your code can pass - a good test is one that reveals a problem.

The test set developed should include, for each test:

When coming up with a test set, there are three major categories to consider:

Black box testing
In glass box testing we are only interested in testing the functionality of the program: we have the problem description that tells us how a correct solution is supposed to behave, so we establish test data that we think is representative of the possible input conditions the program will ultimately face.

Common black box tests:

Glass box testing
As covered in the black box section, we can derive many test sets directly from the specifications.

However, it is often useful to also consider the "inside information" we have about the actual structure of the code.

The testing ideas are the same as above, but now there are more data values of interest:


Example
Suppose we're given the following specifications for our software
The program is supposed to read two times, each in the format hh:mm:ss, and output the time difference between the two.

The program should verify the correctness of the input, and it is not permissible to omit leading zeros in the hours segment of the time.

For example, if the times 09:59:59 and 10:01:00 are entered then the program should respond with 00:01:01.

A 24-hour clock is assumed, with times running from 00:00:00 to 23:59:59. If the first time is later than the second time then it is assumed the clock has "wrapped around" once.

For example, if the times 23:00:01 and 01:24:01 are entered then the program should respond with 02:24:00.

Then we might propose the following black box tests
Test rationale Time 1 Time 2 Correct Output
text in time 1hh:mm:ss12:00:00*ERRMESSAGE
text in time 212:00:00hh:mm:ss*ERRMESSAGE
missing leading zero, hours time 10:00:0012:00:00*ERRMESSAGE
missing leading zero, minutes time 100:0:0012:00:00*ERRMESSAGE
missing leading zero, seconds time 100:00:012:00:00*ERRMESSAGE
missing leading zero, hours time 200:00:002:00:00*ERRMESSAGE
missing leading zero, minutes time 200:00:0012:0:00*ERRMESSAGE
missing leading zero, seconds time 200:00:0012:00:0*ERRMESSAGE
time out of bounds, hours time 124:00:0012:00:00*ERRMESSAGE
time out of bounds, minutes time 100:60:0012:00:00*ERRMESSAGE
time out of bounds, seconds time 100:00:6012:00:00*ERRMESSAGE
time out of bounds, hours time 220:00:0024:00:00*ERRMESSAGE
time out of bounds, minutes time 200:00:0012:60:00*ERRMESSAGE
time out of bounds, seconds time 200:00:0012:00:60*ERRMESSAGE
boundary case - all zeros00:00:0000:00:00*ERRMESSAGE
boundary case - max time-of-days23:59:5923:59:59*ERRMESSAGE
max time difference, no rollover00:00:0023:59:5923:59:59
max time difference, includes rollover12:00:0112:00:0023:59:59
min time difference with rollover23:59:5900:00:0000:00:01
"typical" case, no rollover07:24:3911:28:4704:04:08
"typical" case, with rollovers16:27:5508:12:5115:44:56
*The content of the error messages should also be included

Now, suppose we implement the program as follows

#include <cstdio>

void PromptUser();

void ReadTime(int& hours, int& minutes, int& seconds);

void CalcTimeDifference(
             int& hrs_res, int& min_res, int& sec_res,
             int  hrs1,    int  min1,    int  sec1,
             int  hrs2,    int  min2,    int  sec2);

void DisplayTime(int hrs_res, int min_res, int sec_res);

int main()
{
    int Hours1, Minutes1, Seconds1;
    int Hours2, Minutes2, Seconds2;
    int ResultHours, ResultMinutes, ResultSeconds;

    PromptUser();
    ReadTime(Hours1, Minutes1, Seconds1);
    ReadTime(Hours2, Minutes2, Seconds2);

    CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
             Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);

    DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
    return 0;
}

void PromptUser()
{
   printf("This program calculates the difference between two times,\n");
   printf("assuming the two times are within 24 hours of one another\n");
   printf("and are entered in sequential order\n\n");
}

void ReadTime(int& hours, int& minutes, int& seconds)
{
    char ColonChar;
    printf("Please enter a time in the form hh:mm:ss\n");
    printf("assuming a 24-hour clock, and leading zeros must be included\n");
    printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
    scanf("%d", &hours);
    scanf("%c", &ColonChar);
    scanf("%d", &minutes);
    scanf("%c", &ColonChar);
    scanf("%d", &seconds);
}

void CalcTimeDifference(
             int& hrs_res, int& min_res, int& sec_res,
             int  hrs1,    int  min1,    int  sec1,
             int  hrs2,    int  min2,    int  sec2)
{
   sec_res = sec2 - sec1;
   min_res = min2 - min1;
   hrs_res = hrs2 - hrs1;
   if (sec_res < 0) {
      sec_res = sec_res + 60;
      min_res = min_res - 1;
   } 
   if (min_res < 0) {
      min_res = min_res + 60;
      hrs_res = hrs_res - 1;
   }
   if (hrs_res < 0) {
      hrs_res = hrs_res + 24;
   }
}

void DisplayTime(int hrs_res, int min_res, int sec_res)
{
   if (hrs_res < 10) printf("0");
   printf("%d:", hrs_res);
   if (min_res < 10) printf("0");
   printf("%d:", min_res);
   if (sec_res < 10) printf("0");
   printf("%d:", sec_res);
}
Which additional glass box tests might we propose?
combination Time 1 Time 2
aaa 10:10:10 09:09:09
aab 10:10:02 09:09:11
aac 10:10:22 09:09:32
aba 10:02:10 09:11:09
abb 10:02:02 09:11:11
abc 10:02:22 09:11:32
aca 10:22:10 09:32:09
acb 10:22:02 09:32:11
acc 10:22:22 09:32:32
aaa 02:10:10 11:09:09
aab 02:10:02 11:09:11
aac 02:10:22 11:09:32
aba 02:02:10 11:11:09
abb 02:02:02 11:11:11
abc 02:02:22 11:11:32
aca 02:22:10 11:32:09
acb 02:22:02 11:32:11
acc 02:22:22 11:32:32
aaa 22:10:10 32:09:09
aab 22:10:02 32:09:11
aac 22:10:22 32:09:32
aba 22:02:10 32:11:09
abb 22:02:02 32:11:11
abc 22:02:22 32:11:32
aca 22:22:10 32:32:09
acb 22:22:02 32:32:11
acc 22:22:22 32:32:32

Exception Handling
Exception handling is the process by which we deal with any "unusual circumstances" during execution. Typically this covers things like the entry of incorrect data or failures in other parts of a system we must use (e.g. suppose our program interacts with a database program, and for some reason the database program crashes).

Exception handling on a practical level involves inserting sufficient error checking into our source code to ensure that any possible errors are caught and an appropriate response generated (even if the "response" is just displaying an error message and shutting down the program).

The key to successful exception handling is to assume, in each and every function, that the other functions are not necessarily trustworthy - i.e. don't assume the error checking was adequately done elsewhere.
Example: suppose we have the following function

float divides(float x, float y)
{
   return (x / y);
}
For the sake of robustness, we should not assume y is never zero - i.e. we should check for it, and generate an appropriate error message.
float divides(float x, float y)
{
   if (y != 0) 
      return (x / y);
   else {
      printf("WARNING: DIVIDE BY ZERO\n");
      return 0;
   }
}

Example: for the time-difference example discussed earlier, the source code with exception handling built in might look more like:
#include <cstdio>

void PromptUser();

int TimeCheck(int hours, int minutes, int seconds);

void ReadTime(int& hours, int& minutes, int& seconds);

void CalcTimeDifference(
             int& hrs_res, int& min_res, int& sec_res,
             int  hrs1,    int  min1,    int  sec1,
             int  hrs2,    int  min2,    int  sec2);

void DisplayTime(int hrs_res, int min_res, int sec_res);

int main()
{
    int Hours1, Minutes1, Seconds1;
    int Hours2, Minutes2, Seconds2;
    int ResultHours, ResultMinutes, ResultSeconds;

    PromptUser();
    ReadTime(Hours1, Minutes1, Seconds1);
    ReadTime(Hours2, Minutes2, Seconds2);

    CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
             Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);

    printf("\nThe time difference is: ");
    DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
    return 0;
}

void PromptUser()
{
   printf("\nThis program calculates the difference between two times,\n");
   printf("assuming the two times are within 24 hours of one another\n");
   printf("and are entered in sequential order\n");
}

void ReadTime(int& hours, int& minutes, int& seconds)
{
    char ColonChar;
    printf("\nPlease enter a time in the form hh:mm:ss\n);
    printf("assuming a 24-hour clock, and leading zeros must be included\n");
    printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
    scanf("%d", &hours);
    scanf("%c", &ColonChar);
    scanf("%d", &minutes);
    scanf("%c", &ColonChar);
    scanf("%d", &seconds);
    if (TimeCheck(hours, minutes, seconds) == 0)
    {
       printf("WARNING: invalid time supplied\n");
       ReadTime(hours, minutes, seconds);
    }
}

int TimeCheck(int hours, int minutes, int seconds)
{
    if ((hours < 0) || (hours > 23)) 
       return 0;
    if ((minutes < 0) || (minutes > 59))
       return 0;
    if ((seconds < 0) || (seconds > 59))
       return 0;
    return 1;
}

void CalcTimeDifference(
             int& hrs_res, int& min_res, int& sec_res,
             int  hrs1,    int  min1,    int  sec1,
             int  hrs2,    int  min2,    int  sec2)
{
   if (TimeCheck(hrs1, min1, sec1) == 0)
      return;
   if (TimeCheck(hrs2, min2, sec2) == 0)
      return;
   sec_res = sec2 - sec1;
   min_res = min2 - min1;
   hrs_res = hrs2 - hrs1;
   if (sec_res < 0) {
      sec_res = sec_res + 60;
      min_res = min_res - 1;
   } 
   if (min_res < 0) {
      min_res = min_res + 60;
      hrs_res = hrs_res - 1;
   }
   if (hrs_res < 0) {
      hrs_res = hrs_res + 24;
   }
}

void DisplayTime(int hrs_res, int min_res, int sec_res)
{
   if (TimeCheck(hrs_res, min_res, sec_res) == 0)
   {
      printf("Invalid time supplied, hours=");
      printf("%d, minutes=", hrs_res);
      printf("%d, seconds=", min_res);
      printf("%d\n", sec_res);
      return;
   }
   if (hrs_res < 10) printf("0");
   printf("%d:", hrs_res);
   if (min_res < 10) printf("0");
   printf("%d:", min_res);
   if (sec_res < 10) printf("0");
   printf("%d\n", sec_res);
}

Incremental Development

When implementing, compiling, and testing
  1. first get a skeleton (outline) solution for the problem
  2. get it implemented, running, and tested
  3. flesh out one more part of the program
  4. get it implemented, running, and tested
  5. repeat steps 3 and 4 until the whole thing is done
If you design and code the whole thing in one fell swoop then try to compile/debug it you may find the problems overwhelming.

Suppose we were going to approach the development of our "time difference" program in an incremental fashion. The steps I would advise are:


  1. Create the main program and "empty" versions of the functions it uses, i.e.:
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        printf("\nThe time difference is: ");
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("In PromptUser\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
       printf("In ReadTime\n");
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        printf("In TimeCheck\n");
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       printf("In CalcTimeDifference\n");
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       printf("In DisplayTime\n");
    }
    

  2. Put in a body for DisplayTime, and try it with a test value
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        printf("\nThe time difference is: ");
        ResultHours = 12;
        ResultMinutes = 12;
        ResultSeconds = 12;
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("In PromptUser\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
       printf("In ReadTime\n");
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        printf("In TimeCheck\n");
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       printf("In CalcTimeDifference\n");
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (hrs_res < 10) printf("0)";
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0)";
       printf("%d:", min_res);
       if (sec_res < 10) printf("0)";
       printf("%d\n", sec_res);
    }
    

  3. Add the body for the prompt routine
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        printf("\nThe time difference is: ");
        ResultHours = 12;
        ResultMinutes = 12;
        ResultSeconds = 12;
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("\nThis program calculates the difference between two times,\n");
       printf("assuming the two times are within 24 hours of one another"\n");
       printf("and are entered in sequential order\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
       printf("In ReadTime\n");
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        printf("In TimeCheck\n");
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       printf("In CalcTimeDifference\n");
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (hrs_res < 10) printf("0");
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0");
       printf("%d:", min_res);
       if (sec_res < 10) printf("0");
       printf("%d\n", sec_res);
    }
    

  4. Add the body for the ReadTime routine and adjust main a bit to allow testing
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        // editing for testing, just echo hours read in
        ResultHours = Hours1;
        ResultMinutes = Minutes1;
        ResultSeconds = Seconds1;
    
        printf("\nThe time difference is: ");
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("\nThis program calculates the difference between two times,\n");
       printf("assuming the two times are within 24 hours of one another\n");
       printf("and are entered in sequential order\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
        char ColonChar;
        printf("\nPlease enter a time in the form hh:mm:ss\n");
        printf("assuming a 24-hour clock, and leading zeros must be included\n");
        printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
        scanf("%d", &hours);
        scanf("%c", &ColonChar);
        scanf("%d", &minutes);
        scanf("%c", &ColonChar);
        scanf("%d", &seconds);
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        printf("In TimeCheck\n");
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       printf("In CalcTimeDifference\n");
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (hrs_res < 10) printf("0");
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0");
       printf("%d:", min_res);
       if (sec_res < 10) printf("0");
       printf("%d\n", sec_res);
    }
    

  5. Add the routine to test data validity, and try it with the input/output routines
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        // Again, adjusted just for checking I/O, 
        //    still not really calculating time differences
        printf("\nThe time difference is: ");
        DisplayTime(Hours1, Minutes1, Seconds1);
        DisplayTime(Hours2, Minutes2, Seconds2);
        return 0;
    }
    
    void PromptUser()
    {
       printf("This program calculates the difference between two times,\n");
       printf("assuming the two times are within 24 hours of one another\n");
       printf("and are entered in sequential order\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
        char ColonChar;
        printf("Please enter a time in the form hh:mm:ss\n");
        printf("assuming a 24-hour clock, and leading zeros must be included\n");
        printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
        scanf("%d", &hours);
        scanf("%c", &ColonChar);
        scanf("%d", &minutes);
        scanf("%c", &ColonChar);
        scanf("%d", &seconds);
        if (TimeCheck(hours, minutes, seconds) == 0)
        {
           printf("WARNING: invalid time supplied"\n");
           ReadTime(hours, minutes, seconds);
        }
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        if ((hours < 0) || (hours > 23)) 
           return 0;
        if ((minutes < 0) || (minutes > 59))
           return 0;
        if ((seconds < 0) || (seconds > 59))
           return 0;
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       printf("In CalcTimeDifference\n");
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (TimeCheck(hrs_res, min_res, sec_res) == 0)
       {
          printf("Invalid time supplied, hours=");
          printf("%d, minutes=", hrs_res);
          printf("%d, seconds=", min_res);
          printf("%d\n", sec_res);
          return;
       }
       if (hrs_res < 10) printf("0");
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0");
       printf("%d:", min_res);
       if (sec_res < 10) printf("0");
       printf("%d\n", sec_res);
    }
    

  6. Add the basic computations for calculating differences
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        printf("\nThe time difference is: ");
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("This program calculates the difference between two times,\n");
       printf("assuming the two times are within 24 hours of one another\n");
       printf("and are entered in sequential order\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
        char ColonChar;
        printf("\nPlease enter a time in the form hh:mm:ss\n");
        printf("assuming a 24-hour clock, and leading zeros must be included\n");
        printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
        scanf("%d", &hours);
        scanf("%c", &ColonChar);
        scanf("%d", &minutes);
        scanf("%c", &ColonChar);
        scanf("%d", &seconds);
        if (TimeCheck(hours, minutes, seconds) == 0)
        {
           printf("WARNING: invalid time supplied\n");
           ReadTime(hours, minutes, seconds);
        }
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        if ((hours < 0) || (hours > 23)) 
           return 0;
        if ((minutes < 0) || (minutes > 59))
           return 0;
        if ((seconds < 0) || (seconds > 59))
           return 0;
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       sec_res = sec2 - sec1;
       min_res = min2 - min1;
       hrs_res = hrs2 - hrs1;
       if (sec_res < 0) {
          sec_res = sec_res + 60;
          min_res = min_res - 1;
       } 
       if (min_res < 0) {
          min_res = min_res + 60;
          hrs_res = hrs_res - 1;
       }
       if (hrs_res < 0) {
          hrs_res = hrs_res + 24;
       }
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (TimeCheck(hrs_res, min_res, sec_res) == 0)
       {
          printf("Invalid time supplied, hours=");
          printf("%d, minutes=", hrs_res);
          printf("%d, seconds=", min_res);
          printf("%d\n=", sec_res);
          return;
       }
       if (hrs_res < 10) printf("0");
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0");
       printf("%d:", min_res);
       if (sec_res < 10) printf("0");
       printf("%d\n", sec_res);
    }
    

  7. Add the error checking for calculating time differences
    #include <cstdio>
    
    void PromptUser();
    
    int TimeCheck(int hours, int minutes, int seconds);
    
    void ReadTime(int& hours, int& minutes, int& seconds);
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2);
    
    void DisplayTime(int hrs_res, int min_res, int sec_res);
    
    int main()
    {
        int Hours1, Minutes1, Seconds1;
        int Hours2, Minutes2, Seconds2;
        int ResultHours, ResultMinutes, ResultSeconds;
    
        PromptUser();
        ReadTime(Hours1, Minutes1, Seconds1);
        ReadTime(Hours2, Minutes2, Seconds2);
    
        CalcTimeDifference( ResultHours, ResultMinutes, ResultSeconds,
                 Hours1, Minutes1, Seconds1, Hours2, Minutes2, Seconds2);
    
        printf("\nThe time difference is: ");
        DisplayTime(ResultHours, ResultMinutes, ResultSeconds);
        return 0;
    }
    
    void PromptUser()
    {
       printf("This program calculates the difference between two times,\n");
       printf("assuming the two times are within 24 hours of one another\n");
       printf("and are entered in sequential order\n");
    }
    
    void ReadTime(int& hours, int& minutes, int& seconds)
    {
        char ColonChar;
        printf("Please enter a time in the form hh:mm:ss\n");
        printf("assuming a 24-hour clock, and leading zeros must be included\n");
        printf("(i.e. times go from 00:00:00 to 23:59:59)\n");
        scanf("%d", &hours);
        scanf("%c", &ColonChar);
        scanf("%d", &minutes);
        scanf("%c", &ColonChar);
        scanf("%d", &seconds);
        if (TimeCheck(hours, minutes, seconds) == 0)
        {
           printf("WARNING: invalid time supplied\n");
           ReadTime(hours, minutes, seconds);
        }
    }
    
    int TimeCheck(int hours, int minutes, int seconds)
    {
        if ((hours < 0) || (hours > 23)) 
           return 0;
        if ((minutes < 0) || (minutes > 59))
           return 0;
        if ((seconds < 0) || (seconds > 59))
           return 0;
        return 1;
    }
    
    void CalcTimeDifference(
                 int& hrs_res, int& min_res, int& sec_res,
                 int  hrs1,    int  min1,    int  sec1,
                 int  hrs2,    int  min2,    int  sec2)
    {
       if (TimeCheck(hrs1, min1, sec1) == 0)
          return;
       if (TimeCheck(hrs2, min2, sec2) == 0)
          return;
       sec_res = sec2 - sec1;
       min_res = min2 - min1;
       hrs_res = hrs2 - hrs1;
       if (sec_res < 0) {
          sec_res = sec_res + 60;
          min_res = min_res - 1;
       } 
       if (min_res < 0) {
          min_res = min_res + 60;
          hrs_res = hrs_res - 1;
       }
       if (hrs_res < 0) {
          hrs_res = hrs_res + 24;
       }
    }
    
    void DisplayTime(int hrs_res, int min_res, int sec_res)
    {
       if (TimeCheck(hrs_res, min_res, sec_res) == 0)
       {
          printf("Invalid time supplied, hours=");
          printf("%d, minutes=", hrs_res);
          printf("%d, seconds=", min_res);
          printf("%d\n", sec_res);
          return;
       }
       if (hrs_res < 10) printf("0");
       printf("%d:", hrs_res);
       if (min_res < 10) printf("0");
       printf("%d:", min_res);
       if (sec_res < 10) printf("0");
       printf("%d\n", sec_res);
    }
    

The debugging process

Debugging should not be a hit-or-miss proposition where you simply hack at the code, changing structures or values in the hopes that something will fall into place.

If you have thought out your test plan as per the discussion above, and you're building your software in an incremental fashion, then you already have an excellent start on debugging: you have a focus on which segment of the source code is (most likely) the source of any current problems, and you have a rationale for each test set that gives you a basis for investigating further.

One of the key goals in debugging is to constantly narrow the sources of your current error - visual inspection of the code may not be sufficient. Try to identify new test values you can use to precisely determine when and why your program crashes, hangs, or simply gives incorrect data.

Debugging software is helpful, but often is not enough to track down the cause of a problem unless you also make careful (and sometimes creative) deductions about what your program is doing and why.

In addition to fuse, we also have available a debugger named gdb that can be run from a terminal window. To invoke this debugger, follow the steps below (example is shown assuming pex2.C is the source code file):

g++ -g pex2.C -o pex2
gdb pex2
The debugger will come back with a prompt that looks like
(gdb)
You can now execute a variety of commands that allow you to To examine the options type h when you see the (gdb) prompt.