Example: sample C++ program for debugging

The program below is used in various topics to demonstrate debugging tasks.

This program is a simple calculator that reads its input from a character buffer. If integers are read, they are pushed on a stack. If one of the operators (+ - * ⁄) is read, the top two elements are popped off the stack, the operation is performed on them, and the result is pushed on the stack. The = operator writes out the value of the top element of the stack to a buffer.

CALC.HPP
/*----- FILE CALC.HPP ------------------------------------------------*/
/*                                                                    */
/* Header file for CALC.CPP PUSHPOP.CPP READTOKN.CPP                  */
/* a simple calculator                                                */
/*--------------------------------------------------------------------*/
typedef enum toks {
  T_INTEGER,
  T_PLUS,
  T_TIMES,
  T_MINUS,
  T_DIVIDE,
  T_EQUALS,
  T_STOP
} Token;
extern "C" Token read_token(char buf[]);
class IntLink {
  private:
    int i;
    IntLink * next;
  public:
    IntLink();
    ~IntLink();
    int get_i();
    void set_i(int j);
    IntLink * get_next();
    void set_next(IntLink * d);
};
class IntStack {
  private:
    IntLink * top;
  public:
    IntStack();
    ~IntStack();
    void push(int);
    int pop();
};
CALC.CPP
/*----- FILE CALC.CPP ------------------------------------------------*/
/*                                                                    */
/* A simple calculator that does operations on integers that          */
/* are pushed and popped on a stack                                   */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "calc.hpp"
IntStack stack;
int main()
{
  Token tok;
  char word[100];
  char buf_out[100];
  int num, num2;
  for(;;)
  {
    tok=read_token(word);
    switch(tok)
    {
      case T_STOP:
        break;
      case T_INTEGER:
        num = atoi(word);
        stack.push(num);      ⁄*  CALC1  statement *⁄
        break;
      case T_PLUS:
        stack.push(stack.pop()+stack.pop());
        break;
      case T_MINUS:
        num = stack.pop();
        stack.push(num-stack.pop());
        break;
      case T_TIMES:
        stack.push(stack.pop()*stack.pop() );
        break;
      case T_DIVIDE:
        num2 = stack.pop();
        num = stack.pop();
        stack.push(num⁄num2);      ⁄*  CALC2  statement *⁄
        break;
      case T_EQUALS:
        num = stack.pop();
        sprintf(buf_out,"= %d ",num);
        stack.push(num);
        break;
    }
    if (tok==T_STOP)
      break;
  }
  return 0;
}
PUSHPOP.CPP
/*----- FILE: PUSHPOP.CPP --------------------------------------------*/
/*                                                                    */
/* Push and pop functions for a stack of integers                     */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "calc.hpp"
/*--------------------------------------------------------------------*/
/* input:  num - value to push on the stack                           */
/* action: get a link to hold the pushed value, push link on stack    */
/*--------------------------------------------------------------------*/
void IntStack::push(int num) {
  IntLink * ptr;
  ptr = new IntLink;
  ptr–>set_i(num);
  ptr–>set_next(top);
  top = ptr;
}
/*--------------------------------------------------------------------*/
/* return: int value popped from stack (0 if stack is empty)          */
/* action: pops top element from stack and get return value from it   */
/*--------------------------------------------------------------------*/
int IntStack::pop() {
  IntLink * ptr;
  int num;
  ptr = top;
  num = ptr–>get_i();
  top = ptr–>get_next();
  delete ptr;
  return num;
}
IntStack::IntStack() {
  top = 0;
}
IntStack::~IntStack() {
  while(top)
    pop();
}
IntLink::IntLink() {  ⁄* constructor leaves elements unassigned *⁄
}
IntLink::~IntLink() {
}
void IntLink::set_i(int j) {
  i = j;
}
int IntLink::get_i() {
  return i;
}
void IntLink::set_next(IntLink * p) {
  next = p;
}
IntLink * IntLink::get_next() {
  return next;
}
READTOKN.CPP
/*----- FILE READTOKN.CPP --------------------------------------------*/
/*                                                                    */
/* A function to read input and tokenize it for a simple calculator   */
/*--------------------------------------------------------------------*/
#include <ctype.h>
#include <stdio.h>
#include "calc.hpp"
/*--------------------------------------------------------------------*/
/* action: get next input char, update index for next call            */
/* return: next input char                                            */
/*--------------------------------------------------------------------*/
static char nextchar(void)
{
  ⁄*    input  action
   *    -----  ------
   *    2      push 2 on stack
   *    18     push 18
   *    +      pop 2, pop 18, add, push result (20)
   *    =      output value on the top of the stack (20)
   *    5      push 5
   *    ⁄      pop 5, pop 20, divide, push result (4)
   *    =      output value on the top of the stack (4)
   *⁄
  char * buf_in  = "2 18 + = 5 ⁄ = ";
  static int index;     ⁄* starts at 0 *⁄
  char ret;
  ret = buf_in[index];
  ++index;
  return ret;
}
/*--------------------------------------------------------------------*/
/* output: buf - null terminated token                                */
/* return: token type                                                 */
/* action: reads chars through nextchar() and tokenizes them          */
/*--------------------------------------------------------------------*/
extern "C"
Token read_token(char buf[])
{
  int i;
  char c;
  ⁄* skip leading white space *⁄
  for( c=nextchar();
       isspace(c);
       c=nextchar())
    ;
  buf[0] = c;  ⁄* get ready to return single char e.g. "+" *⁄
  buf[1] = 0;
  switch(c)
  {
    case '+' : return T_PLUS;
    case '-' : return T_MINUS;
    case '*' : return T_TIMES;
    case '⁄' : return T_DIVIDE;
    case '=' : return T_EQUALS;
    default:
      i = 0;
      while (isdigit(c)) {
        buf[i++] = c;
        c = nextchar();
      }
      buf[i] = 0;
      if (i==0)
        return T_STOP;
      else
        return T_INTEGER;
  }
}

Refer to the following topics for more information related to the material discussed in this topic.