CSCI 200 - Spring 2023
Foundational Programming Concepts & Design

Style Guidelines


Style Guidelines



· main.cpp · Functions.h · Functions.cpp · Template.hpp · Class.h · Class.cpp · AbstractClass.h · AbstractClass.cpp · ConcreteClass.h · ConcreteClass.cpp · Makefile ·

main.cpp

// this is a single line comment

/*
 *  this is a block comment that
 *  can span several lines
 */

// place all header files you've written together, in alphabetical order
// include only the header files you need
#include "AbstractClass.h"
#include "Class.h"
#include "ConcreteClass.h"
#include "Functions.h"
#include "Template.hpp"

// place all C++ standard libraries together, in alphabetical order
// include only the libraries you need
#include <fstream>          // for file streams (ifstream, ofstream)
#include <iomanip>          // for I/O Manipulators (precision, aligning, etc.)
#include <iostream>         // for standard input/output
#include <string>           // for string library
#include <vector>           // for vector library
using namespace std;        // we are using the standard namespace

// place all C standard libraries together, in alphabetical order
// include only the libraries you need
#include <cctype>           // for tolower(), isalpha(), etc.
#include <cmath>            // for sqrt(), pow(), sin(), etc.
#include <cstdlib>          // for srand(), rand()
#include <ctime>            // for time()

/*
 * any variables defined above main() are in global scope and can be
 *  accessed anywhere.  This is generally BAD.
 * Only declare & define constants in global scope.
 * Constants are named using UPPER_SNAKE_CASE to denote it as an
 * immutable value
 */
const double PI_VALUE = 3.1415926535;

// structs are named using UpperCamelCase to denote it is a datatype
struct ClassRoom {
  string buildingName;
  int roomNumber;
};

// every program must have a main() function
//  - it is the entry point to our program
int main(int argc, char* argv[]) {  // the curly brace begins a new code block
  srand( time(0) );                 // seed the RNG - do this once per program as first statement

  // indent the contents of a code block a two spaces length

  // Template for variable declaration
  //        anything inside of [brackets] is optional
  // Version1: [modifiers] dataType identifierName [= initialValue];
  // Version2: [modifiers] dataType identifierName[(initialValue)];

  int ageOfColosseum;               // declare a variable
                                    // use lowerCamelCase to make a descriptive variable name
  ageOfColosseum = 1940;            // define a variable (assign a value)

  int numRomanEmperors = 71;        // declare and define a variable in one line

  const int VATICAN_BUILT = 1626;   // declare and define a constant
                                    // must define a constant when it is declared
                                    // use UPPER_SNAKE_CASE to make a descriptive constant name

  // declare (and define) multiple variables of the same type at once
  char firstInitial = 'I', secondInitial('T'), currentEmperorInitial;

  cout << "The Colosseum was built in 70-80 A.D. and is "
       << ageOfColosseum << " years old." << endl;
  cout << endl;

  // when  prompting the user to enter a value via cin, preceed the input with a prompt
  //    using cout so the user knows what to enter
  int currentYear;
  cout << "Please enter the current 4 digit year (e.g. 1999): ";
  cin >> currentYear;
  cout << "St. Peter's Basilica was built in " << VATICAN_BUILT
       << " and is " << (currentYear - VATICAN_BUILT) << " years old." << endl;

  if( currentYear >= 2400 ) {
    // indent the contents of a new code block
    cout << "Duck Dodgers of the 24th and a Half Century!" << endl;
  } else if( currentYear >= 2000 ) {    // place else if and else on the same line the prior code block ends
    cout << "In the year 2000, robots will do 80% of the work. - Conan O'Brien." << endl;
  } else {
    // use curly braces to denote a code block for if/else if/else even if the code
    //     block only has one statement
    cout << "Let's party like it's 1999. - Prince" << endl;
  }

  for( int i = 0; i < 10; i++ ) {
    // indent the contents of a new code block
    // use a code block for a for loop even if it contains only a single statement
    cout << i << endl;
  }

  char userResponse;
  do {
    cout << "Enter a letter (q to quit): ";
    cin >> userResponse;
  } while( userResponse != 'q' );   // place the while on the same line as the end of the do

  // for function calls, add spaces within the () and after each argument
  cout << "5 + 3 = " << calculator_add( 5, 3 ) << endl;
  cout << "5 - 3 = " << calculator_sub( 5, 3 ) << endl;

  ClassRoom lectureLab;             // create a variable of our custom struct type
  lectureLab.building = "Brown";    // access components of a structure using dot operator
  lectureLab.roomNumber = 316;

  cout << "The length of the building name is: "
       << lectureLab.building.length()      // access string functions with dot operator
       << endl;

  // Template for vector declaration
  //        anything inside of [brackets] is optional
  // Version1: [const] vector< dataType > identifierName;
  // Version2: [const] vector< dataType > identifierName[(initialSize)];
  // Version3: [const] vector< dataType > identifierName[(initialSize, initialValue)];
  vector<int> numbers;              // create an empty vector of integers
  numbers.push_back( 5 );           // add the value 5 to the vector
  numbers.at( 0 ) = 6;              // access individual elements using the at() function

  Calculator fourFunctionCalc( 4.5, 3.5 );  // object names follow lowerCamelCase
  cout << fourFunctionCalc.getLeftHandSide() << " + " << fourFunctionCalc.getRightHandSide() << " = "
       << fourFunctionCalc.add() << endl;
  fourFunctionCalc.setLeftHandSide( 13.0 );
  fourFunctionCalc.setRightHandSide( 1.5 );
  cout << fourFunctionCalc.getLeftHandSide() << " / " << fourFunctionCalc.getRightHandSide() << " = "
       << fourFunctionCalc.divide() << endl

  int arraySize;
  cout << "How many elements do you have? ";
  cin >> arraySize;

  // pointer variables begin with a p and follow lowerCamelCase style
  int* pArray = new int[arraySize];      // allocate an array of integers
  for( int i = 0; i < arraySize; i++ ) {
    cout << "Enter array value: ";
    cin >> pArray[i];
  }
  delete[] pArray;                       // deallocate the array of integers

  cout << "3 + 4 = "
       << apply_add_operator( 3, 4 ) << endl;

  cout << "\"Hello,\" + \"World\" = "
       << apply_add_operator( "Hello,", "World" ) << endl;

  cout << "0.5 + 0.25 = "
       << apply_add_operator( 0.5f, 0.25f ) << endl;

  ListInt* pList = new ArrayInt();       // declare pointer as abstract type and point at concrete instance
  pList->insert( 0, 5 );                 // list contents: 5
  pList->insert( 1, 7 );                 // list contents: 5 7
  cout << "List size is " << pList->getSize() << endl;  // prints 2
  pList->remove( 0 );                    // list contents: 7
  delete pList;

  return 0;                              // alert the OS our program exited with result 0 (success)
}   // the curly brace ends the code block that it corresponds to
    // every open brace needs a matching end brace

Functions.h

// place header guards around all your header files
// make the name of the file the name of the value to test for
// use UPPER_SNAKE_CASE for your definition value
#ifndef FUNCTIONS_H         // ask compiler if FUNCTIONS_H has been defined
#define FUNCTIONS_H         // if not, define FUNCTIONS_H

// place ALL function prototypes into the header file
// use lower_snake_case for top level free functions

/**
 * @brief adds two integers together
 * @desc Returns the integer sum of two integer parameters
 * @param x first operand to add
 * @param y second operand to add
 * @return sum of x and y
 */
int calculator_add( int x, int y );

/**
 * @brief subtracts two integers
 * @desc Returns the integer difference of y from x (x - y)
 * @param value to start with
 * @param value to subtract
 * @return difference of x and y
 */
int calculator_sub( int x, int y );

#endif // FUNCTIONS_H       // ends the corresponding #ifndef

Functions.cpp

#include "Functions.h"                     // include the file with the corresponding prototypes

int calculator_add( int x, int y ) {       // function definition
  return x + y;
}

int calculator_sub( int x, int y ) {
  return x - y;
}

Template.hpp

// place header guards around all your header files
// make the name of the file the name of the value to test for
// use UPPER_SNAKE_CASE for your definition value
#ifndef TEMPLATE_HPP                 // ask compiler if TEMPLATE_HPP has been defined
#define TEMPLATE_HPP                 // if not, define TEMPLATE_HPP

// when a function or class is templated, its type cannot be known with the corresponding
// usage.  place the corresponding declaration and definition together in a single
// hpp file to denote
//   *.h*  - this is a header file containing declarations
//   *.*pp - this file contains definitions

// place the definitions at the top of the follow to maintain abstraction

/**
 * @brief resolves the binary plus operator for two values of the same type
 * @desc resolves the binary plus operator for two values of the same type as long
 * as the operator is defined for the correspond type
 * @param VAL_ONE left hand side of addition
 * @param VAL_TWO right hand side of addition
 * @return VAL_ONE + VAL_TWO
 */
template<typename T>
T apply_add_operator(const T VAL_ONE, const T VAL_TWO);

//----------------------------------------------------------------------------

// place the corresponding function declarations below to maintain abstraction

template<typename T>
T apply_add_operator(const T VAL_ONE, const T VAL_TWO) {
  return VAL_ONE + VAL_TWO;
}

#endif // TEMPLATE_HPP               // ends the corresponding #ifndef

Class.h

// place header guards around all your header files
// make the name of the file the name of the value to test for
// use UPPER_SNAKE_CASE for your definition value
#ifndef CLASSNAME_H                 // ask compiler if CLASSNAME_H has been defined
#define CLASSNAME_H                 // if not, define CLASSNAME_H

// place a single Class declaration into its own file

class Calculator {                  // class names follow UpperCamelCase
public:
  /**
   * @brief creates a default calculator
   * @desc Creates a default calculator with both operands set to 1
   */
  Calculator();                     // provide a default constructor
  /**
   * @brief creates a default calculator
   * @desc Creates a default calculator with both operands set to 1
   * @param LHS left hand side of calculation
   * @param RHS right hand side of calculation
   */
  Calculator(const double, const double);       // provide a parameterized constructor

  // create The Big Three if appropriate for memory management
  // Calculator(const Calculator&);             // copy constructor
  // ~Calculator();                             // destructor
  // Calculator& operator=(const Calculator&);  // copy assignment operator

  // create getters and setters (if appropriate) for your private data members
  /**
   * @brief return the left hand side operand
   * @return value of left hand side operand
   */
  double getLeftHandSide() const;   // getters are const functions
  /**
   * @brief set the left hand side operand
   * @param LHS value of left hand side operand
   */
  void setLeftHandSide(const double);

  /**
   * @brief return the right hand side operand
   * @return value of right hand side operand
   */
  double getRightHandSide() const;
  /**
   * @brief set the right hand side operand
   * @param RHS value of right hand side operand
   */
  void setRightHandSide(const double);

  // add any other related functions and mark as const if they do not change the callee
  /**
   * @brief return the sum of the operands
   * @return LHS + RHS
   */
  double add() const;
  /**
   * @brief return the difference of the operands
   * @return LHS - RHS
   */
  double subtract() const;
  /**
   * @brief return the product of the operands
   * @return LHS * RHS
   */
  double multiply() const;
  /**
   * @brief return the division of the operands
   * @return LHS / RHS
   */
  double divide() const;

private:
  double mLeftHandSide;             // private members begin with m
  double mRightHandSide;
};

#endif // CLASSNAME_H               // ends the corresponding #ifndef

Class.cpp

#include "Class.h"          // include the file with the corresponding prototypes

Calculator::Calculator() {
  mLeftHandSide = 1.0;
  mRightHandSide = 1.0;
}

Calculator::Calculator(const double LHS, const double RHS) {
  mLeftHandSide = LHS;
  mRightHandSide = RHS;
}

double Calculator::getLeftHandSide() const {
  return mLeftHandSide;
}
void Calculator::setLeftHandSide(const double LHS) {
  mLeftHandSide = LHS;
}

double Calculator::getRightHandSide() const {
  return mRightHandSide;
}
void Calculator::setRightHandSide(const double RHS) {
  mRightHandSide = RHS;
}

double Calculator::add() const {
  return mLeftHandSide + mRightHandSide;
}

double Calculator::subtract() const {
  return mLeftHandSide - mRightHandSide;
}

double Calculator::multiply() const {
  return mLeftHandSide * mRightHandSide;
}

double Calculator::divide() const {
  if( mRightHandSide != 0 ) {
    return mLeftHandSide / mRightHandSide;
  } else {
    return 0.0;
  }
}

AbstractClass.h

// place header guards around all your header files
// make the name of the file the name of the value to test for
// use UPPER_SNAKE_CASE for your definition value
#ifndef ABSTRACT_CLASSNAME_H                 // ask compiler if ABSTRACT_CLASSNAME_H has been defined
#define ABSTRACT_CLASSNAME_H                 // if not, define ABSTRACT_CLASSNAME_H

// place a single Class declaration into its own file

class ListInt {                              // class names follow UpperCamelCase
public:
  /**
   * @brief initialize list size to zero
   * @desc initializes list size to zero
   */
  ListInt();

  /**
   * @brief returns the size of the list
   * @desc returns the size of the list
   * @return list size
   */
  int getSize() const;

  /**
   * @brief add an integer value to the list
   * @desc inserts the corresponding value immediately before the specified position.
   *   list size is increased by one
   * @param POS position to insert before
   * @param VAL value to insert
   */
  virtual void insert(const int POS, const int VAL) = 0;    // create an abstract function with no definition

  /**
   * @brief removes the value at the corresponding position
   * @desc if the position is within range, removes the corresponding element.  list size
   *   is decreased by one
   * @param POS position to remove at
   */
  virtual void remove(const int POS) = 0;    // create a pure virtual function with no definition

protected:
  int mSize;                                 // protected data members begin with m
};

#endif // ABSTRACT_CLASSNAME_H               // ends the corresponding #ifndef


AbstractClass.cpp

#include "AbstractClass.h"

ListInt::ListInt() {
  mSize = 0;
}

int ListInt::getSize() const {
  return mSize;
}


ConcreteClass.h

// place header guards around all your header files
// make the name of the file the name of the value to test for
// use UPPER_SNAKE_CASE for your definition value
#ifndef CONCRETE_CLASSNAME_H                 // ask compiler if CONCRETE_CLASSNAME_H has been defined
#define CONCRETE_CLASSNAME_H                 // if not, define CONCRETE_CLASSNAME_H

// place a single Class declaration into its own file

#include "AbstractClass.h"

class ArrayInt final : public ListInt {      // class names follow UpperCamelCase
                                             // use public inheritance to follow the exposed interface of the parent class
                                             // mark concrete classes as final to close them
public:
  /**
   * @brief add an integer value to the list
   * @desc inserts the corresponding value immediately before the specified position.
   *   list size is increased by one
   * @param POS position to insert before
   * @param VAL value to insert
   */
   void insert(const int POS, const int VAL) override final;    // mark concrete functions as overridden and final

  /**
   * @brief removes the value at the corresponding position
   * @desc if the position is within range, removes the corresponding element.  list size
   *   is decreased by one
   * @param POS position to remove at
   */
  void remove(const int POS) override final;  // mark concrete functions as overridden and final
};

#endif // CONCRETE_CLASSNAME_H               // ends the corresponding #ifndef


ConcreteClass.cpp

#include "ConcreteClass.h"          // include the file with the corresponding prototypes

void ArrayInt::insert(const int POS, const int VAL) {
  mSize++;
  // provide implementation
}

void ArrayInt::remove(const int POS) {
  mSize--;
  // provide implementation
}

Makefile

# COMMENTS BEGIN WITH A HASH

# THE NAME OF YOUR EXECUTABLE
TARGET = StyleGuideExample
# ALL CPP COMPILABLE IMPLEMENTATION FILES THAT MAKE UP THE PROJECT
SRC_FILES = main.cpp AbstractClass.cpp Class.cpp ConcreteClass.cpp Functions.cpp

# NO EDITS NEEDED BELOW THIS LINE

CXX = g++
CFLAGS = -Wall -g -std=c++11

OBJECTS = $(SRC_FILES:.cpp=.o)

ifeq ($(shell echo "Windows"), "Windows")
    TARGET := $(TARGET).exe
    DEL = del
else
    DEL = rm
endif

all: $(TARGET)

$(TARGET): $(OBJECTS)
    $(CXX) -o $@ $^

.cpp.o:
    $(CXX) $(CFLAGS) -o $@ -c $<

clean:
    $(DEL) $(TARGET) $(OBJECTS)

# DEPENDENCIES
main.o: main.cpp AbstractClass.h Class.h ConcreteClass.h Functions.h Template.hpp
AbstractClass.o: AbstractClass.cpp AbstractClass.h
Class.o: Class.cpp Class.h
ConcreteClass.o: ConcreteClass.cpp ConcreteClass.h AbstractClass.h
Functions.o: Functions.cpp Functions.h