CS 200: Concepts of Programming using C++ (Summer 2024 version)

Table of Contents


Rachel Wil Sha Singh's Core C++ Course © 2024 by Rachel Wil Sha Singh is licensed under CC BY 4.0. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/


1. Navigating this course

Resources used in this class:


Contacting the instructor:


  • The best way to contact me is via the in-Canvas email system, not through @jccc email.
  • I also have a Discord char server for their classes, feel free to join in order to ask questions. The join link is here: https://discord.gg/A2mgwrUeAj
  • We can also schedule time to meet on campus or via Zoom based on your availability.
  • Since this is an 8 week class I would recommend reaching out as soon as you need help with something rather than waiting.


Unlocking content in this class:


  • Class content is segmented into Modules on Canvas. A set of modules will be unlocked and available to start with, and to unlock further content in the class you need to pass the Mastery Check module every-so-often.
  • The Mastery Check milestone contains an exam and a project. The project needs to be submitted and the mastery check you need to score at least 70% on to unlock the next set of items.
  • You can retake the exams but you need to email me in order for me to unlock the exam for you. Exams are built randomly from a pool of questions.
  • Since this is the summer semester you will need to figure out a schedule of how many modules you want to tackle per week. I have a suggested schedule a little later on.
    • We have 8 weeks and 16 modules, though module size varies.
  • The last day of class in Summer 2024 is Thursday, July 25th, so all assignments must be in by this time.
  • Most assignments can be redone for an improved grade as well.
  • See the Syllabus chapter in this book for more details about the course.


1.1. Recommended Summer 2024 schedule

This schedule is recommended, but the modules are available whenever you meet the prerequisites for any of them.

Week # Monday Topics
1 June 3 Unit 00: Welcome and setup
    Unit 01: Tech Literacy: Exploring computers
    Unit 02: C++: Variables, input, and output
2 June 10 Milestone: Mastery Check 1
    Unit 03: C++: Functions
    Unit 04: Tech Literacy: Debugging and researching
3 June 17 Milestone: Mastery Check 2
    Unit 05: C++: Structs
    Unit 06: Tech Literacy: Careers in tech
4 June 24 Unit 07: C++: Looping
    Unit 08: C++: Arrays and vectors
5 July 1 Milestone: Mastery Check 3
    Unit 09: C++: Branching
    Unit 10: C++ Searching and sorting
6 July 8 Unit 11: Tech Literacy: Current trends in tech
    Unit 12: Tech Literacy: Object Oriented Programming, UML
    Unit 13: C++: Classes and inheritance
7 July 15 Milestone: Mastery Check 4
    Unit 14: C++: Strings and File I/O
    Unit 15: Tech Literacy: Ethics in tech
8 July 22 Unit 16: C++: Intro to recursion


2. Reference

2.1. C++ quick reference

C++ basics

  • Starter C++ program:

    int main()               int main( int argCount, char* args[] )
    {                        {
      return 0;                return 0;
    }                        }
  • Declare a variable: DATATYPE VARIABLENAME;

    int myNumber;      string myString;      float myFloat;
  • Declare a variable and initialize it: DATATYPE VAR = VALUE;

    int myNumber = 10;   string myString = "Hello!";    float myFloat = 9.99;
    char myChar = 'a';   bool myBool = true;
  • Declare a named constant: const DATATYPE NAME = VALUE;

    const int NUMBER = 10;      const string STATE = "Missouri";
  • Assign a value to a variable that has already been declared: VAR = VALUE;

    myNumber = 100;             myString = "Goodbye";
  • Copy a value from one variable to another: RECEIVER = COPYME;

    vipStudent = student3;
  • Output text to the console: cout << ITEM << ITEM << endl;
    • You can mix variables (VAR) and string literals ("HI"), as long as the stream operator << is between each item.
  • Get input from the keyboard and store it in a variable: cin >> VAR;
  • Get a full line of text and store in a string: getline( cin, VAR );

    • Only works with string variables.
    • Note that if you have a cin >> statement immediately before the getline statement, your input will get skipped. In this case you need to add a cin.ignore() statement:
    cin >> myNumber;
    getline( cin, myString );



  • If statements:

    // IF STATEMENT                   // IF/ELSE STATEMENT
    if ( a == 1 )                     if ( a == 1 )
    {                                 {
      // Executes when a == 1           // Executes when a == 1
    }                                 }
                                        // Executes when a != 1
    if ( a == 1 )                     if ( a == 1 )
    {                                 {
        // Executes when a == 1         // Executes when a == 1
    }                                 }
    else if ( a == 2 )                else if ( a == 2 )
    {                                 {
        // Executes when a != 1         // Executes when a != 1
        // and a == 2                   // and a == 2
    }                                 }
                                        // Executes when a != 1
                                        // and a != 2
    • If: If the condition evaluates to true, then execute the code within the if statement. Otherwise, skip that code completely.
    • If/else: If the condition from if statement results to false, then the code in the else case is executed instead. No condition is written with the else case.
    • If/else if statement: Checks each condition in order. If one is true, then subsequent else if statements are ignored.
    • If/else if/else statement: Similar to above, but if all if and else if statements are false, then else is executed.


Switch statements

  • Switch statement: switch( VARIABLE ) { case VALUE: break; }

    • The switch variable can be int, char, but not string.
    switch( myNumber )
      case 1:  cout << "It's one!" << endl; break;
      case 2:  cout << "It's two!" << endl; break;
      default: cout << "I don't know what it is!" << endl;


  • Conditional loops:

    // WHILE LOOP                   // DO...WHILE LOOP
    while ( a < b )                 do
    {                               {
      cout << a << endl;              cout << "Enter a number: ";
      a++;                            cin >> input;
    }                               } while ( input < 0 || input > max );
    • Looping with While Loops: while ( CONDITION ) { }
      • Runs 0 or more times, depending on whether the CONDITION is true.
    • Looping with Do…While Loops: do { } while ( CONDITION );
      • Runs at least once and then continues looping if the condition is true.
  • For loops:

    for ( int i = 0; i < 10; i++ )         vector<int> myVec = { 1, 2, 3, 4 };
    {                                      for ( int element : myVec )
      cout << i << endl;                   {
    }                                        cout << element << endl;
    • Traditional for loops: for ( INIT; CONDITION; UPDATE ) { }
      • Iterate some amount of times through the loop based on your counter variable and range.
    • Range-based for loops: for ( INIT : RANGE ) { }
      • Iterates over all elements in a collection. Only moves forward, doesn't give access to index



  • Declare a traditional C-style array: DATA_TYPE ARRAY_NAME[SIZE];
    • When declaring a vanilla array, you need to set its size. You can either hard-code the size with a number or use a named constant.
  • Declare an STL array object: array<DATA_TYPE, SIZE> ARRAY_NAME;
  • Declare an STL vector object: vector<DATA_TYPE> VECTOR_NAME;
  • Initialize array/vector with an initializer list:

    vector<string> cats3 = { "Kabe", "Luna", "Pixel", "Korra" };
  • Iterate over an array/vector:

    // STL Array and STL Vector:
    for ( size_t i = 0; i < bankBalances.size(); i++ )
      cout << "index: " << i << ", value: " << students[i] << endl;
    • size_t is another name for an unsigned int, which allows values of 0 and above - no negatives.

File input and output

  • Reading and writing with ifstream and ofstream:

    ofstream output;                   ifstream input;
    output.open( "file.txt" );         input.open( "file.txt" );
                                       if ( input.fail() )
    // Write to text file              {
    output << "Hello, world!";           cout << "ERROR!" << endl;
                                       string buffer;
                                       // read a word
                                       input >> buffer;
                                       // read a line
                                       getline( input, buffer );
  • Create an output file and write with ofstream (output file stream)
  • Create an input file and read with ifstream (input file stream)
    • INFILE >> VAR; to read one word at a time
    • getline( INFILE, VAR ); to read one line at a time
  • Make sure to have #include <fstream> in any files using ifstream or ofstream!
  • Prevent file duplication with File Guards: When creating .h/.hpp files, it is important to include these lines to prevent file duplication, which happens if you #include this file in more than one place.

    #define _FILENAME_H
    // Code goes here
  • Function declaration: A function declaration contains the function header and no body. It declares that the function exists and will be defined elseware.

    // NO output return          // int output return
    // NO input parameters       // two int input parameters
    void DisplayMenu();          int Sum(int a, int b);
  • Function definition: A function definition defines how the function operates. It includes the function header and a function body, which has commands in it.

    void DisplayMenu()                      int Sum(int a, int b)
    {                                       {
      cout << "1. Deposit" << endl;           return a + b;
      cout << "2. Withdraw" << endl;        }
      cout << "3. Quit" << endl;
  • Calling a function: Calling a function requires invoking the function's name and passing in any arguments.

    int result = Sum( 1, 2 ); // Passing in literal values
    int num1 = 2;
    int num2 = 5;
    int result = Sum( num1, num2 ); // Passing in variable values



  • Declaring a class: Remember that classes must end with ; on their closing curly brace!

    // EXAMPLE              // STUDENT CLASS
    class CLASSNAME         class Student
    {                       {
        public:             public:
                              // Constructor functions
        protected:            Student( string new_name, float new_gpa );
                              // Member functions
        private:              void Setup( string new_name, float new_gpa );
                              void Display();
                              // Member variables
                              string name;
                              float gpa;
  • Defining a class member function (method): RETURNTYPE CLASSNAME::FUNCTIONNAME( PARAMETERS )

    • A class' member functions must be declared within the class declaration. Then, you define the member function within a .cpp file.
    // Function definition
    void Student::Setup( string name, float gpa )
      m_name = name;
      m_gpa = gpa;


  • Getter function, aka Accessor:
    • Doesn't take in any inputs (parameters)
    • Returns the value of the member variable (return type should match the member variable)
    • Getter functions can be good for formatting data before returning it
// Basic getter function     // Example of formatting before returning data
float Student::GetGPA()      string Person::GetFullName()
{                            {
  return m_gpa;                return m_lastname + ", " + m_firstname;
}                            }
  • Setter function, aka Mutator:
    • Takes in an input value for a new value for the member variable - parameter should have the same data type as the member variable
    • Doesn't return any data - void return type
    • Setter functions should include any needed error checking and reject invalid data
// Basic setter function                // Example of data validity check
void Student::SetGPA( float newGpa )    void Student::SetGPA( float newGpa )
{                                       {
  m_gpa = newGpa;                         if ( newGpa < 0 || newGpa > 4 )
}                                         {
                                            cout << "Error! Invalid GPA!" << endl;
                                            return; // Return without saving data
                                            m_gpa = newGpa;


  • Declare a pointer: DATATYPE* PTRNAME = nullptr;
  • Assign an address to a pointer: PTRNAME = &VARIABLE;
    • Pointer variables store addresses as their value. To get the address of a variable, prefix the variable name with the address-of operator &.
  • Dereference a pointer: *PTRNAME
  • Dereference an object pointer and access a member variable: PTRNAME->MEMBER
int * ptrInt = nullptr;
string * ptrString = nullptr;

string name = "Bob";      // Normal variable
string * ptrName = &name; // Pointer

cout << *ptrName; // Display contents that pointer is pointing to
cin >> *ptrName; // Overwrite contents that pointer is pointing to

Student* newStudent = new Student;
newStudent->name = "Hikaru";
cout << "Student name: " << newStudent->name << endl;

if ( ptrName != nullptr )
  // Pointer is safe to use...
  • Allocate memory for a single variable: DATATYPE* PTRNAME = NEW DATATYPE;
  • Deallocate memory of a single variable: DELETE PTRNAME;
  • Allocate memory for an array: DATATYPE* PTRNAME = new DATATYPE[ SIZE ];
  • Deallocate memory of an array: DELETE [] PTRNAME;
// ALLOCATE MEMORY                        // DEALLOCATE MEMORY
int * num = new int;                      delete num;
Node* newNode = new Node;                 delete newNode;

int * numList = new int[100];             delete [] numList;
Node* nodeList = new Node[10];            delete [] nodeList;


2.2. Basic computer skills

  • How to take a screenshot:
    In Windows

    Press PRINTSCREEN on your keyboard, then go to an image editing application (Paint, if you have nothing else) and use EDIT > PASTE to paste the image in.


    In Mac
    CTRL+Z, COMMAND+SHIFT+3 to take a screenshot in Mac
  • Identifying file extensions: You should be aware of the extensions of our files. You will need to be able to identify source code files, such as .cpp and .h files for C++, or .py files for Python. Additionally, most executable (runnable) files end with the .exe extension in Windows.
  • Turning on viewing file extensions in Windows: By default, Windows hides file extensions from you. However, it is important to know what kind of files you're working with in a programming class. To view file extensions, search for "File Explorer Options". Select the "View" tab, and UNCHECK the option "Hide extensions for known file types". Hit OK when done.


  • Project working directory: It is important to keep in mind that the default working directory of our programs is the location where the project file is.
    • When building and running from the command line (or VS Code Terminal), the working directory should be the folder you're running the program from.
    • For Visual Studio, the working directory is the same location as your project .vcxproj file.
    • For Code::Blocks, the working directory is the same location as your project .cbp file.
  • Handy document navigation
    • Cut, Copy, and Paste
      • Copy: You can highlight text and use EDIT > COPY or CTRL+C to copy it.
      • Cut: You can highlight text and use EDIT > CUT or CTRL+X to cut it.
      • Paste: You can paste copied/cut text by using EDIT > PASTE or CTRL+V.
    • Up and down
      • HOME: The HOME key on your keyboard will take you to the top of a webpage. For a text document use CTRL+HOME to go to the top.
      • END: The END key on your keyboard will take you to the bottom of a webpage. For a text document use CTRL+END to go to the bottom.
    • Highlighting text
      • Double-click a word with your mouse to auto-highlight the entire word.
      • CTRL+A or EDIT > SELECT ALL will highlight your entire document.
  • Handy filesystem navigation
    • Hold down CTRL while clicking on separate folders/files to select multiple.
    • Click on a starting folder/file, hold SHIFT, then click the ending folder/file to highlight all items between those two.


2.3. Common C++ bugs and issues

Common build errors

  • Undefined Reference to WinMain
    • Explanation: Your program can't find main(), the main entry-point to the program.
    • Try:
      • Make sure you've written int main() in your prgoram.
      • If working with Visual Studio, make sure you've opened a project (NOT A FILE/FOLDER!) - Is your Solution Explorer empty?
  • Undefined reference to …
    • Explanation: A variable or function either has not been declared or cannot be found at the current location in the program.
    • Try: Check to make sure you don't have any typos, that your variables have been declared, that your #include are set up properly, and that any functions declared also are defined elseware.
  • Use of undeclared identifier XYZ
    • Explanation: You're trying to use a variable XYZ but you have not declared it at this point in the program.
    • Try: Look for your variable declaration and make sure it shows up before any code that uses this variable.
  • Unresolved external symbol ABC
    • Explanation: This usually means you've made a call to a function that doesn't exist - perhaps you've declared it somewhere, but never wrote the function's definition.
    • Try: Double checking that all your function declarations' and definitions' headers MATCH!
  • Object of abstract class type is not allowed / Cannot instantiate abstract class
    • Explanation: You're trying to create an object (that is, a variable whose data type is a class), and the class you're using is still an abstract class. This could be because you haven't overridden all of its parents' pure virtual functions, or perhaps a typo between the parent class' function signature and the child class' function signature.
    • Try: Look at class' parent - for any pure virtual functions (e.g., virtual RETURN FUNC() = 0;), make sure you have declared and defined them in the child class.


  • Cannot convert from ABC to XYZ
    • Explanation: The program is expecting an XYZ data type in a location where you're giving it an ABC type instead.
    • Try: If you're working with a class object, perhaps you need to pass a member variable of that class object instead?
  • ABC already defined in XYZ
    • Explanation: This error is saying that a function has already been defined elsewhere. There could be a few reasons.
    • Try:
      • Are you missing the #ifndef file guards in a .h file?
      • Have you defined a given function more than once?
      • Run a Clean and Rebuild in your IDE.
      • Make sure that you DO NOT HAVE #include FOR ANY .cpp FILES!!
  • Operator -> applied to ABC instead of pointer type
    • Explanation: You're trying to dereference an object that is not a pointer.
    • Try: Perhaps you're storing a vector of pointers? Make sure you're accessing a single element.
  • Error: implicit instantiation of undefined template std::basic_ifstream
    • Explanation: Missing an include for the fstream library.
    • Try: Don't forget to put #include <fstream> in the code files where you're using ifstream or ofstream.


Weird software issues

  • Windows maximum path length error
    • Explanation: Windows has a setting that limits the maximum file path length. If your repository is deep down many folders, you may encounter this issue.
    • Fixes:
      • Enable long paths - The Windows documentation (docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation) has some information on enabling long paths.
      • OR Move your project directory - If you move your project directory to something like C:\ instead of the desktop (which is actually C:\Users\blahblahblah\Desktop) or the default visual studio project path (C:\Users\blahblahblah\source\repos) this will help avoid this maximum path length issue.
  • Visual Studio: Fatal error LNK1104: cannot open file …exe
    • Explanation: Visual Studio is trying to build the program but cannot overwrite the .exe file.
    • Fixes:
      • Try to close Visual Studio and re-open it - Sometimes if your program crashed last time you ran it, Visual Studio will be unable to update the .exe file and give this error.
      • OR Turn off your virus scan - Sometimes your virus scan will see the .exe file you just built as an ``unknown threat'' and prevent it from opening, which also causes this error.
  • Code::Blocks: error: ld returned 1 exit status
    • Try: Make sure you do not have any #include statements that include a .cpp file. Includes only work with .h and .hpp files, or library files in < > brackets.
  • Code::Blocks: Modern C++ features not working
    • Fix: In this case you'll need to set up your compiler to build for a modern C++ version, rather than the default of C++98 (from 1998). In Code::Blocks, go to Settings > Compiler… Then, check the box that is next to the Have g+ follow the C++17 ISO C++ language standard [-std=c++17] option, or the C++14 one if that's not available.


  • XCode: Cannot find functions
    • Explanation: This is a result of creating a new file in XCode, but choosing the wrong file type. When adding .cpp files, make sure you select a C++ file object.


  • XCode: Where are my output/input text files??
    • You will need to set up a Working Path for your projects in XCode. You can get to this option by going to the menu bar: Scheme -> Edit Scheme. You will want to set your working directory to a specific path where you can locate the text files.



Git issues

  • Git: There is no tracking information for the current branch.

    • Explanation: Git isn't sure what branch you're working with; tell it explicitly.
    • Try: git pull origin main
  • Git: [rejected] error: failed to push some refs

    • Explanation: There are changes on the server that you don't have on your local machine yet. A merge needs to happen.
    • Try: The hint gives you the solution: Run git pull and then repeat your git push after the merge.
  • Git: fatal: not a git repository (or any of the parent directories): .git

    • Explanation: You are not running your git commands from within a repository folder.
    • Try: Make sure you open Git Bash within a folder, or use the cd commands to navigate to your repository path.
  • Git: error: Browse.VC.opendb Permission denied

    • Explanation: This happens because Visual Studio is still open and Visual Studio dislikes its project files changing.
    • Try: Close Visual Studio before running git add.


2.4. Code and UI style guide

Repository management

  • For your course folder, lab assignments should be labeled clearly and consistently (e.g., u02_TopicABC, u03_TopicXYZ)
  • Sync (add / commit / pull / push) frequently, and especially before starting a new assignment.
  • Your merge request should only contain files related to the current feature or project you're working on It shouldn't contain code from multiple assignments.

User Interface design

  • Prompts before inputs:
    • Before using an input statement (e.g., cin), use an output statement (e.g., cout) to display a message to the user. Make sure you're clear about what kind of data you're expecting them to enter.
    • NO: If you use an input statement it doesn't show anything on the screen, so it looks like your program has crashed.

      \begin{lstlisting}[style=terminal] My Program _ \end{lstlisting}
    • YES: Use an output statement to display a message before getting the user's input.

      \begin{lstlisting}[style=terminal] My Program Please enter pet name: _ \end{lstlisting}
  • Utilize numbered menus:
    • Prefer using menus with number options instead of letters, as all the numbers are near each other on the keyboard, whereas with letters the user will have to hunt-and-peck for the option they want.
    • NO:

      \begin{lstlisting}[style=terminal] MAIN MENU N. New game L. Load game S. Save game X. Exit \end{lstlisting}
    • YES:

      \begin{lstlisting}[style=terminal] MAIN MENU 1. New game 2. Load game 3. Save game 0. Exit \end{lstlisting}
  • Validate user input:
    • If the user enters an invalid selection, the program sohuld display an error message before asking them to re-enter their selection. Otherwise, the user will see the program did nothing but not know why.
    • NO:

      \begin{lstlisting}[style=terminal] Your selection: 100 Your selection: 50 Your selection: 2 Loading game... \end{lstlisting}
    • YES:

      \begin{lstlisting}[style=terminal] Your selection: 100 ERROR - Invalid choice! Must be between 0 and 3! Your selection: 2 Loading game... \end{lstlisting}

C++ Style Guide

  • Naming conventions
    • Variables lowerCamelCase - Variable names should begin with a lower-case letter and each subsequent letter use an Upper Case, in a camel-case format.


      • Variable names should be descriptive.
      • Avoid using single-letter variable names except with for loops.
    • Member variables m_lowerCamelCase - Variables that belong to a class should be prefixed with m_ to signify "member".
    • Functions CamelCase - Function names should begin with an upper-case letter and be in CamelCase form. In some cases, using an underscore might be okay to group like-functions together, if it makes things more clear.
    • Classes CamelCase - Class names should begin with an upper-case letter and be in CamelCase form.

Best practices

  • Basics
    • You must have int main, not void main.
    • Don't put an entire program in main() - Split out the program into separate menu functions; ideally use a Program class that contains functions within it.
  • Naming conventions
    • Variable, function, and class names should be descriptive.
  • Arrays
    • Do not use a variable for an array's size; some compilers might support this but not all do. Traditional C arrays and STL arrays must have hard-coded integer literals or named constant integers as its size.
  • Functions
    • Functions should perform the minimal amount of operations - a function should have a specific purpose.
  • Structs and Classes
    • Structs should be used for structures that only contain a few amount of variables and no functions. Classes should be used for more sophisticated structures that contain functions and variables.
    • Prefer making member variables private with member functions as an interface for those items.
  • try/catch
    • The try{} statement should wrap the most minimal amount of code (NOT THE ENTIRE FUNCTION BODY!) - generally, try should wrap the one function that could throw an exception.

Cross platform compatibility

  • Treat everything (including files) as case-sensitive When using an #include statement for a file in your project, make sure your casing matches the file itself. E.g., if the file is Product.h, use #include "Product.h", not #include "product.h".
  • Use #ifndef fileguards, not #pragma once Use the #ifndef _LABEL, #define _LABEL, #endif style of file guards as they are supported by more compilers.
    • Fileguards ONLY go in .h files.


  • The system("cls"); command only works on Windows
    • Prefer creating a cross-platform function like this instead:

      \begin{lstlisting}[style=cpp] void ClearScreen() { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) system( "cls" ); #else system( "clear" ); #endif } \end{lstlisting}
  • The system("pause"); command only works on Windows
    • Prefer creating a cross-platform function like this instead:

      \begin{lstlisting}[style=cpp] // It's klugey but it's the simplest. void PressEnterToContinue() { cout << endl << "PRESS ENTER TO CONTINUE" << endl; string temp; getline( cin, temp ); getline( cin, temp ); } \end{lstlisting}
  • File guards: Always use ifndef instead of pragma once for your file guards.
    • YES:

      \begin{lstlisting}[style=cpp] #ifndef _MYFILE_H #define _MYFILE_H // My code #endif \end{lstlisting}
    • NO:

      \begin{lstlisting}[style=cpp] #pragma once // My code \end{lstlisting}


File organization

  • Function/class declarations
    • Function and class declarations should go in a header (.h) file.
  • Function definitions
    • Function definitions should go in a source (.cpp) file, EXCEPT TEMPLATED FUNCTIONS (those all go in .h).
  • Each class/struct should have its own set of .h and .cpp (as needed) files
    • Don't put multiple class declarations in one file.
  • Function definitions must go in .cpp file
    • Don't define class functions within the class or in the .h file.
    • Except for templated classes - Everything goes in the .h file for templated classes.
  • Don't define structs/classes inside other classes
    • Each struct/class should have its own .h file/set of .h and .cpp files.]
  • Never include .cpp files!
    • Includes should only include .h or .hpp header files.
  • If a project has many files, separate them into folders
    • Logically separate related files into subfolders, such as Exceptions, DataStructures, Menus, etc.

Clean code

  • Erase unused codeblocks
    • If you want to make sure to be able to reference old code later, back it up to GitLab, then delete the comment. Don't leave commented out code blocks in turn-in assignments.
  • Be consistent with naming conventions
    • Choose either UpperCaseFunctionNames or lowerCaseFunctionNames but don't interchange them. Same with variable and class naming. Be consistent.
  • Whitespace
    • Adequate whitespace should be used to differentiate logical sections of code.
    • At the same time, don't use too much whitespace. The goal is to have readable code.
  • If ( true ) return true; else return false;
    • If you're writing a condition to check if something is true in order to return true, just return the result of the condition instead.
    • NO:

      \begin{lstlisting}[style=cpp] if ( a == b ) return true; else return false; \end{lstlisting}
    • YES:

      \begin{lstlisting}[style=cpp] return ( a == b ); \end{lstlisting}

Curly braces

  • Follow the existing code base
    • If you're writing code from scratch you can follow whatever style you'd like as long as it is consistent.
    • When working with existing code-bases, use the same style as the existing code.
    • See https://en.wikipedia.org/wiki/Indentation_style for indentation styles

Preferred style:

\begin{lstlisting}[style=cpp] if ( a == b ) { DoThing(); } \end{lstlisting}

GNU styling:

\begin{lstlisting}[style=cpp] if ( a == b ) { DoThing(); } \end{lstlisting}

K&R Styling ("JavaScript" style):

\begin{lstlisting}[style=cpp] if ( a == b ) { DoThing(); } \end{lstlisting}


  • One-line contents
    • Always surround your if statement and while loop contents within curly braces { } even though it's not required for one-line internals.
    • NO:
\begin{lstlisting}[style=cpp] if ( CONDITION ) DoThingA(); else if ( CONDITION2 ) DoThingB(); else DoThingC(); \end{lstlisting}
  • YES 1:
\begin{lstlisting}[style=cpp] if ( CONDITION ) { DoThingA(); } else if ( CONDITION2 ) { DoThingB(); } else { DoThingC(); } \end{lstlisting}
  • YES 2:
\begin{lstlisting}[style=cpp] if ( CONDITION ) { DoThingA(); } else if ( CONDITION2 ) { DoThingB(); } else { DoThingC(); } \end{lstlisting}


Bad user interface examples

Try to space out a program's output by "section" in the program. Don't just barf out all the information to the screen. Sometimes, not all information is required on a given screen.

BAD                               FIXED

################################  #################################
# NEW RECIPE #                    # NEW RECIPE #
##############                    ##############
Enter new recipe name: PB Cups
Enter URL: asdf.com               Enter new recipe name: PB Cups
How many ingredients? 2           Enter URL: asdf.com
Ingredient name:                  How many ingredients? 2
Ingredient unit:                  INGREDIENT 1:
cups                               - Name: Peanut butter
Ingredient amount:                 - Unit of measurement: cups
30                                 - Amount: 2
Ingredient name:
Chocolate                         INGREDIENT 2:
Ingredient unit:                   - Name: Chocolate
cups                               - Unit of measurement: tbsp
Ingredient amount:                 - Amount: 5
                                   Recipe added successfully.


2.5. How to use VSCode

Installing and configuring VSCode

  • On the VSCode website you can download the program for free.
  • Website: https://code.visualstudio.com/Download
  • Select your operating system, the big blue button on top is fine, or you can select one of the smaller buttons for more refined options.
  • Once downloaded, double click on the installer to begin.
    • License Agreement: Click Next
    • Select Destination Location: You can leave it as default and click Next
    • Select Start Menu Folder: You can leave it as default and click Next
    • Select Additional Tasks: Click the checkboxes that say
      • Add "Open with Code" action to Windows Explorer file context menu
      • Add "Open with Code" action to Windows Explorer directory context menu vscode_install4.png
      • (Note: if you're on Mac/Linux this may not be an option.)
    • Ready to Install: Click Install.


Cloning your course repository

  • Once you have a GitLab account, the instructor will set up a course repository for you. This is a folder on a server where you can keep your work backed up. You can sync between the files on your desktop and any changes on the server (the instructor may add new files or make updates to your code to add comments).
  • Copy repo URL:

    vscode_clonerepo_copyurl.png Go to your GitLab repository webpage and locate the blue code button. Click on it, then copy the URL underneath Clone with HTTPS.

  • Clone repository:

    vscode_clonerepo_clonerepository.png Within VSCode, click on the icon on the left that looks like a node branching into two nodes. This is the source control tab. Click on the Clone Repository button.

  • Clone in VS Code: vscode_clonerepo_repourl.png A little box will pop up at the top of VSCode asking for a repository URL. Paste the copied URL from the website here, then hit enter.
  • Select repository destination:

    vscode_clonerepo_setdestination.png It will ask you to set a destination for your course folder. I would suggest putting in in your Documents or Desktop. Once you've found a location, click the Select as Repository Destination button.

  • View on computer:

    vscode_clonerepo_onexplorer.png Once it's been cloned, you will be able to see the folder on your computer under the file explorer. You will work from this directory.

  • As you work through assignments you will periodically back up your work and sync it with the server, but we will cover that later on.

Opening your repository folder

  • Open in VS Code:

    vscode_open1.png Once you're ready to start programming, from the File menu, select Open Folder….

  • Select folder:

    vscode_open_repofolder.png Locate your repository folder (named something like cs200-username-repo). Highlight the folder and click Open Folder.


  • Project view:

    vscode_repo_opened.png You will be able to see all the contents of your repository on the left side.

  • The left view shows you all of the folders and files within the folder you opened.
  • You can double-click one of the folders (which have a > to its left) to open it and you can see the code within the folder. If you double-click a file it will open it in the editor view.
  • The right view shows the currently opened code file. You can edit your code in this view.


VSCode terminal

  • View > Terminal:

    vscode_build_viewterminal.png To open the terminal, click on the View dropdown from the top menu and select Terminal.

  • The Terminal is a text interface, we will use some basic commands to work with our code. The terminal has a prompt, which displays the current folders that you're inside of (called the path), and ends with a > sign. You can type commands after the >.



Command: ls - LiSt files and folders

  • If you type ls (that is a lower-case L and S) and hit ENTER, it will show you the files and folders in this location.


Command: cd - Change Directory

  • If you type cd and the name of a folder, it will move you into that folder. This can be useful to go between your different projects.


  • cd FOLDERNAME will put you inside the folder named, and
  • cd .. will take you out of the current folder you're in.


Building your C++ program

  • Every time you make a change to your C++ source code you will have to compile (aka build) the code into an executable (.exe) file. To do this, we use the g++ compiler program.
  • To run the program, we list the program name first (g++) then give it any options after a space. For g++, the option will be the code file we want to build:


  • g++ test.cpp will build "test.cpp" into an executable file. On Windows, it will generate a.exe. On Linux and Mac, it will generate a.out. You can use the ls command to make sure your program is shown.
  • If the build is successful, g++ won't give you any messages and just return you to the prompt to enter a new command. However, if there are syntax errors in your code, it will display the errors afterwards. You will need to fix any syntax errors in order to get the program to build.

Running your program

  • To run the program, use the ./PROGRAMNAME command, this runs your program. By default, g++ generates a a.exe or a.out file, so to run you would use ./a.exe or ./a.out:


Committing and syncing to back up your work

  • Once you've made any changes to your repository, under the Source Control tab (the branching icon), it will show a little notification bubble with a number in it.


  • From this page, you can back up your changes. In the little text box, add a useful message to keep note of what you changed (e.g., "Fixed bug with input", "Finished with u02 lab"), then click the Commit button to make a backup snapshot.


  • After a commit, the button turns into a Sync Changes button. This will send your changes to the server for long-term storage. You will also need to save your files on the server so that the instructor can see your work. You can click it any time you're doing a commit to back up your work.


  • Once you've synced your work, on the GitLab repo website you will be able to see your latest commit message:


  • If you click on the folder and file that you edited you will be able to see the updates online as well:


Other VSCode notes:

  • VSCode might ask if you want to "periodically run git fetch". Go ahead and click Yes here. This will automatically pull down any changes from the server, such as if the instructor adds additional files.



2.6. How to install Git

Installing Git

The Git software is PC software that allows you to interact with a Git server.

  • Download the installer here: https://git-scm.com/
  • Once donwloaded, double click the installer to begin.
    • Most default options are fine.
    • On the "Choosing the default editor used by Git", just select Notepad, or any other program you recognize there.


  • After installation is done we need to configure it in VS Code.
    • Open VS Code and open up the terminal by going to View > Terminal:


    • Enter each of the following commands in the terminal. (Replace "you@example.com" with your email address)
      • Configure your email address:

        \begin{lstlisting}[style=terminal] git config --global user.email "you@example.com" \end{lstlisting}
      • Configure the name that shows up on GitLab. (Replace "Your Name" with your name)

        \begin{lstlisting}[style=terminal] git config --global user.name "Your Name" \end{lstlisting}
      • Configure how Git handles merging my code vs. your code:

        \begin{lstlisting}[style=terminal] git config --global pull.rebase false \end{lstlisting}


3. Syllabus

3.1. Course information

College Johnson County Community College
Division CSIT (Computer Science/Information Technology)
Instructor Rachel Wil Singh (they/them)
Semester Summer 2024 (06/03/2024 - 07/22/2024)
Course CS 200: Concepts of Programming with C++ (4 credit hours)
Section Section 300 / CRN 60580 / Online-only
Office hours Available by appointment (on campus / Zoom)
Course description
This course emphasizes problem solving using a high-level programming language and the software development process. Algorithm design and development, programming style, documentation, testing and debugging will be presented. Standard algorithms and data structures will be introduced. Data abstraction and an introduction to object-oriented programming will be studied and used to implement algorithms. 3 hrs. lecture, 2 hrs. lab by arrangement/wk. Catalog link: https://catalog.jccc.edu/coursedescriptions/cs/#CS_200
(CS 134 with a grade of "C" or higher or CIS 142 with a grade of "C" or higher or department waiver test and MATH 131 or higher) or MATH 241 or department approval.
Drop deadlines
To view the deadline dates for dropping this course, please refer to the schedule on the JCCC website under Admissions>Enrollment Dates> Dropping Credit Classes. After the 100% refund date, you will be financially responsible for the tuition charges; for details, search on Student Financial Responsibility on the JCCC web page. Changing your schedule may reduce eligibility for financial aid and other third party funding. Courses not dropped will be graded. For questions about dropping courses, contact the Student Success Center at 913-469-3803.
Attendance for the first week of classes at JCCC are recorded and students marked as NOT IN ATTENDANCE get auto-withdrawn from the course. Please pay attention to course announcements / emails from the instructor for instructions on how to make sure you are marked as IN ATTENDANCE.
Instructor information
(no term)
Name: Rachel Wil Singh, aka R.W. (they/them)
(no term)
Office: RC 348 H
(no term)
Email: rsingh13@jccc.edu (please use Canvas email instead)
(no term)
Office phone: (913) 469-8500 x3671
Course delivery

This course is set up as an Online course. This means the following:

  • There is no scheduled class time for this course.
  • Instructions and assignments are given totally online
  • You can utilize office hours to meet with the instructor, ask questions, and get help.

To see more about JCCC course delivery options, please visit: https://www.jccc.edu/student-resources/course-delivery-methods.html


Office hours

Over the summer semester, office hours are optional. You can schedule a time to meet with me on campus or via Zoom (Zoom preferred), just send me an email.


Class communication
(no term)
Please use Canvas email, not the @jccc email, to contact the instructor! I rely upon the Canvas email system for communication with students and only students. The direct @jccc email address also receives non-student communication such as automated campus updates, department emails, commitee emails, and so on. To ensure that I see your email in a timely manner, please email me via Canvas!
(no term)
Instructor will respond within 1 business day I do my best to respond to emails as quickly as possible, at most within 1 business day. Emails on Friday may not get a response until Monday. If I have not responded to your email within this time period it is possible I have not seen your email, please make sure to email me through Canvas and not to my @jccc email.
(no term)
Check course Announcements! I use the Announcements board as a way to give additional course information, assignment corrections, and other things. You can set up Canvas to email these announcements to you automatically. Please don't ignore class Announcements!

3.1.1. Course supplies

  1. Textbook: Rachel's CS 200 course notes (https://moosadee.gitlab.io/courses/)
  2. Zoom: Needed for remote attendance / office hours
  3. Tools: We will go over how to set this up during first week assignments.
    • WINDOWS: MinGW
    • LINUX/MAC: g++
    • VS Code
  4. Accounts: See the UNIT 00 SETUP assignments for steps on set up.
  5. Optional: Things that might be handy
    • Dark Reader plugin (Firefox/Chrome/Safari/Edge) to turn light-mode webpages into dark-mode. (https://darkreader.org/)

3.1.2. Recommended experience

There are certain skills that will make your time in this class easier. Please look over this list and let me know if you need additional help with any of these things.

Computer skills - You should have a base level knowledge of using a computer, including:

  • Navigating your Operating System, including:
    • Installing software
    • Running software
    • Locating saved files on your computer
    • Writing text documents, exporting to PDF
    • Taking screenshots
    • Editing .txt and other plaintext files
  • Navigating the internet:
    • Navigating websites, using links
    • Sending emails
    • Uploading attachments

Learning skills - Learning to program takes a lot of reading, and you will be building up your problem solving skills. You should be able to exercise the following skills:

  • Breaking down problems - Looking at a problem in small pieces and tackling them one part at a time.
  • Organizing your notes so you can use them for reference while coding.
  • Reading an entire part of an assignment before starting - these aren't step-by-step to-do lists.
  • Learning how to ask a question - Where are you stuck, what are you stuck on, what have you tried?
  • Recognizing when additional learning resources are needed and seeking them out - such as utilizing JCCC's Academic Achievement Center tutors.
  • Managing your time to give yourself enough time to tackle challenges, rather than waiting until the last minute.

How to ask questions - When asking questions about a programming assignment via email, please include the following information so I can answer your question:

  1. Be sure to let me know WHICH ASSIGNMENT IT IS, the specific assignment name, so I can find it.
  2. Include a SCREENSHOT of what's going wrong.
  3. What have you tried so far?

3.2. Course policies

3.2.1. Grading breakdown

Assessment types are given a certain weight in the overall class. Breakdown percentages are based off the course catalog requirements (https://catalog.jccc.edu/coursedescriptions/cs/#CS_200)

  • Labs: Weekly programming assignments to help practice new concepts (20%)
  • Exercises: A variety of additional topics to help students learn and practice (5%)
  • Nonograms: Small puzzles to help students practice problem solving and analysis
  • Tech Literacy discussions: Discussions about tech related areas (5%)
  • Check-ins: Weekly Check-Ins to let me know how you're doing in the course and if you need anything additional (5%)
  • Concept Introductions (Quizzes): Concept Introductions help students review concepts read about in the textbook (10%)
  • Projects: Larger programming assignments that combine multiple topics (15%)
  • Exams: Mastery Checks to help the student and instructor assess how much about a topic has been learned (40%)

Final letter grade: JCCC uses whole letter grades for final course grades: F, D, C, B, and A. The way I break down what your receive at the end of the semester is as follows:

Total score Letter grade
89.5% \(\leq\) grade \(\leq\) 100% A
79.5% \(\leq\) grade < 89.5% B
69.5% \(\leq\) grade < 79.5% C
59.5% \(\leq\) grade < 69.5% D
0% \(\leq\) grade < 59.5% F

3.2.2. Tentative schedule

This schedule is recommended, but the modules are available whenever you meet the prerequisites for any of them.

Week # Monday Topics
1 June 3 Unit 00: Welcome and setup
    Unit 01: Tech Literacy: Exploring computers
    Unit 02: C++: Variables, input, and output
2 June 10 Milestone: Mastery Check 1
    Unit 03: C++: Functions
    Unit 04: Tech Literacy: Debugging and researching
3 June 17 Milestone: Mastery Check 2
    Unit 05: C++: Structs
    Unit 06: Tech Literacy: Careers in tech
4 June 24 Unit 07: C++: Looping
    Unit 08: C++: Arrays and vectors
5 July 1 Milestone: Mastery Check 3
    Unit 09: C++: Branching
    Unit 10: C++ Searching and sorting
6 July 8 Unit 11: Tech Literacy: Current trends in tech
    Unit 12: Tech Literacy: Object Oriented Programming, UML
    Unit 13: C++: Classes and inheritance
7 July 15 Milestone: Mastery Check 4
    Unit 14: C++: Strings and File I/O
    Unit 15: Tech Literacy: Ethics in tech
8 July 22 Unit 16: C++: Intro to recursion

3.2.3. Class format

Unlocking class content:


  • On Canvas you will have access to a set amount of modules, with a Mastery Check milestone gating access to subsequent modules. Each Mastery Check includes one exam and one project.
  • Exams have a series of multiple choice questions as well as type-in, manually graded questions. You need to score at least 70% on the exam (and turn in the project) to unlock the next set of modules.
  • If you score below 70% (after the write-in questions have been graded) you can retake the exam but you need to reach out to me to unlock it again.
  • Exams are randomly built from a pool of questions, so each attempt will be a little different.

Grade scoring:


  • All assignment scores begin at 0% at the start of the semester, so your grade begins at 0% at the start.
  • As you progress through the course and finish more course content, your grade will continue rising. Ideally, if you get 100% on all assignments in the course, you'll end with 100% as your final grade.
  • Most assignments can be resubmitted after grading to improve your score afterwards. (e.g., if I notice bugs in your lab, I'll make comments on why it happens, and you can go back and fix it.)
  • Assignments don't close until the last day of class - July 25th. See the Academic Calendar (https://www.jccc.edu/modules/calendar/academic-calendar.html) if needed.

3.2.4. Academic honesty

The assignments the instructor writes for this course are meant to help the student learn new topics, starting easy and increasing the challenge over time. If a student does not do their own work then they miss out on the lessons and strategy learned from going from step A to step B to step C. The instructor is always willing to help you work through assignments, so ideally the student shouldn't feel the need to turn to third party sources for help.


Generally, for R.W. Singh's courses:

  • OK things:
    • Asking the instructor for help, hints, or clarification, on any assignment.
    • Posting to the discussion board with questions (except with tests - please email me for those). (If you're unsure if you can post a question to the discussion board, you can go ahead and post it. If there's a problem I'll remove/edit the message and just let you know.)
    • Searching online for general knowledge questions (e.g. "C++ if statements", error messages).
    • Working with a tutor through the assignments, as long as they're not doing the work for you.
    • Use your IDE (replit, visual studio, code::blocks) to test out things before answering questions.
    • Brainstorming with classmates, sharing general information ("This is how I do input validation").
  • Not OK Things:
    • Sharing your code files with other students, or asking other students for their code files.
    • Asking a tutor, peer, family member, friend, AI, etc. to do your assignments for you.
    • Searching for specific solutions to assignments online/elseware.
    • Basically, any work/research you aren't doing on your own, that means you're not learning the topics.
    • Don't give your code files to other students, even if it is "to verify my work!"
    • Don't copy solutions off other parts of the internet; assignments get modified a little bit each semester.

If you have any further questions, please contact the instructor.

Each instructor is different, so make sure you don't assume that what is OK with one instructor is OK with another.

3.2.5. Student success tips

  • I need to achieve a certain grade for my financial aid or student visa. What do I need to plan on?
    • If you need to get a certain grade, such as an A for this course, to maintain your financial aid or student visa, then you need to set your mindset for this course immediately. You should prioritize working on assignments early and getting them in ahead of time so that you have the maximum amount of time to ask questions and get help. You should not be panicking at the end of the semester because you have a grade less than what you need. From week 1, make sure you're committed to staying on top of things.
  • How do I contact the instructor?
    • The best way to contact the instructor is via Canvas' email system. You can also email the instructor at rsingh13@jccc.edu, however, emails are more likely to be lost in the main inbox, since that's where all the instructor's work-related email goes. You can also attend Zoom office hours to ask questions.
  • What are some suggestions for approaching studying and assignments for this course?
    • Each week is generally designed with this "path" in mind:
      • Watch lecture videos, read assigned reading.
      • Work on Concept Introduction assignment(s).
      • Work on Exercise assignment.
    • Those are the core topics for the class. The Tech Literacy assignments can be done a bit more casually, and the Topic Mastery (exams) don't have to be done right away - do the exams once you feel comfortable with the topic.
  • Where do I find feedback on my work?
    • Canvas should send you an email when there is feedback on your work, but you can also locate assignment feedback by going to your Grades view on Canvas, locating the assignment, and clicking on the speech balloon icon to open up comments. These will be important to look over during the semester, especially if you want to resubmit an assignment for a better grade.
  • How do I find a tutor?
  • How do I keep track of assignments and due dates so I don't forget something?
    • Canvas has a CALENDAR view, but it might also be useful to utilize something like Google Calendar, which can text and email you reminders, or even keeping a paper day planner that you check every day.

3.2.6. Accommodations and life help

  • How do I get accommodations? - Access Services


    Access Services provides students with disabilities equal opportunity and access. Some of the accommodations and services include testing accommodations, note-taking assistance, sign language interpreting services, audiobooks/alternative text and assistive technology.

  • What if I'm having trouble making ends meet in my personal life? - Student Basic Needs Center


    Check website for schedule and location. The JCCC Student Assistance Fund is to help students facing a sudden and unforeseen emergency that has affected their ability to attend class or otherwise meet the academic obligations of a JCCC student. If you are experiencing food or housing insecurity, or other hardships, stop by COM 319 and visit with our helpful staff.

  • Is there someone I can talk to for my degree plan? - Academic Advising


    JCCC has advisors to help you with:

    • Choose or change your major and stay on track for graduation.
    • Ensure a smooth transfer process to a 4-year institution.
    • Discover resources and tools available to help build your schedule, complete enrollment and receive help with coursework each semester.
    • Learn how to get involved in Student Senate, clubs and orgs, athletics, study abroad, service learning, honors and other leadership programs.
    • If there’s a hold on your account due to test scores, academic probation or suspension, you are required to meet with a counselor.
  • Is there someone I can talk to for emotional support? - Personal Counseling


    JCCC counselors provide a safe and confidential environment to talk about personal concerns. We advocate for students and assist with personal issues and make referrals to appropriate agencies when needed.

  • How do I get a tutor? - The Academic Achievement Center


    The AAC is open for Zoom meetings and appointments. See the website for their schedule. Meet with a Learning Specialist for help with classes and study skills, a Reading Specialist to improve understanding of your academic reading, or a tutor to help you with specific courses and college study skills. You can sign up for workshops to get off to a Smart Start in your semester or analyze your exam scores!

3.3. Additional information

3.3.1. ADA compliance / disabilities

JCCC provides a range of services to allow persons with disabilities to participate in educational programs and activities. If you are a student with a disability and if you are in need of accommodations or services, it is your responsibility to contact Access Services and make a formal request. To schedule an appointment with an Access Advisor or for additional information, you can contact Access Services at (913) 469-3521 or accessservices@jccc.edu. Access Services is located on the 2nd floor of the Student Center (SC202)

3.3.2. Attendance standards of JCCC

Educational research demonstrates that students who regularly attend and participate in all scheduled classes are more likely to succeed in college. Punctual and regular attendance at all scheduled classes, for the duration of the course, is regarded as integral to all courses and is expected of all students. Each JCCC faculty member will include attendance guidelines in the course syllabus that are applicable to that course, and students are responsible for knowing and adhering to those guidelines. Students are expected to regularly attend classes in accordance with the attendance standards implemented by JCCC faculty.

The student is responsible for all course content and assignments missed due to absence. Excessive absences and authorized absences are handled in accordance with the Student Attendance Operating Procedure.

3.3.3. Academic Dishonesty

No student shall attempt, engage in, or aid and abet behavior that, in the judgment of the faculty member for a particular class, is construed as academic dishonesty. This includes, but is not limited to, cheating, plagiarism or other forms of academic dishonesty.

Examples of academic dishonesty and cheating include, but are not limited to, unauthorized acquisition of tests or other academic materials and/or distribution of these materials, unauthorized sharing of answers during an exam, use of unauthorized notes or study materials during an exam, altering an exam and resubmitting it for re-grading, having another student take an exam for you or submit assignments in your name, participating in unauthorized collaboration on coursework to be graded, providing false data for a research paper, using electronic equipment to transmit information to a third party to seek answers, or creating/citing false or fictitious references for a term paper. Submitting the same paper for multiple classes may also be considered cheating if not authorized by the faculty member.

Examples of plagiarism include, but are not limited to, any attempt to take credit for work that is not your own, such as using direct quotes from an author without using quotation marks or indentation in the paper, paraphrasing work that is not your own without giving credit to the original source of the idea, or failing to properly cite all sources in the body of your work. This includes use of complete or partial papers from internet paper mills or other sources of non-original work without attribution.

A faculty member may further define academic dishonesty, cheating or plagiarism in the course syllabus.

3.3.4. Campus Health Guidelines for COVID-19

Follow College COVID-19 safety guidelines:


  • Stay home when you're sick
  • Wash hands frequently
  • Cover your mouth when coughing or sneezing
  • Clean surfaces
  • Facial coverings are available and welcomed but not required
  • Wear yoru name badge or carry your JCCC photo id while on campus

3.3.8. Campus safety

Information regarding student safety can be found at http://www.jccc.edu/student-resources/police-safety/. Classroom and campus safety are of paramount importance at Johnson County Community College and are the shared responsibility of the entire campus population. Please review the following:

  • Report emergencies: to Campus Police (available 24 hours a day)
    • In person at the Midwest Trust Center (MTC 115)
    • Call 913-469-2500 (direct line) – Tip: program in your cell phone
    • Phone app - download JCCC Guardian (the free campus safety app: www.jccc.edu/guardian) - instant panic button and texting capability to Campus Police
    • Anonymous reports to KOPS-Watch -

      https://secure.ethicspoint.com/domain/en/report_company.asp?clientid=25868 or 888-258-3230

  • Be Alert:
    • You are an extra set of eyes and ears to help maintain campus safety
    • Trust your instincts
    • Report suspicious or unusual behavior/circumstances to Campus Police (see above)
  • Be Prepared:
    • Identify the red/white stripe Building Emergency Response posters throughout campus and online that show egress routes, shelter, and equipment
    • View A.L.I.C.E. training (armed intruder response training - Alert, Lockdown, Inform, Counter and/or Evacuate)
    • Familiarize yourself with the College Emergency Response Plan: (jccc.edu/student-resources/police-safety/college-emergency-response-plan/)
  • During an emergency: Notifications/Alerts (emergencies and inclement weather) are sent to all employees and students using email and text messaging
    • students are automatically enrolled, see JCCC Alert - Emergency Notification: (jccc.edu/student-resources/police-safety/jccc-alert.html)
  • Weapons policy: Effective July 1, 2017, concealed carry handguns are permitted in JCCC buildings subject to the restrictions set forth in the Weapons Policy. Handgun safety training is encouraged of all who choose to conceal carry. Suspected violations should be reported to JCCC Police Department 913-469-2500 or if an emergency, you can also call 911.

3.4. Course catalog info


  1. Describe computer systems and examine ethics.
  2. Solve problems using a disciplined approach to software development.
  3. Utilize fundamental programming language features.
  4. Implement procedures.
  5. Employ fundamental data structures and algorithms.
  6. Write code using object-oriented techniques.
  7. Write code according to commonly accepted programming standards.
  8. Utilize a professional software development environment.

Content Outline and Competencies:

I. Computer Systems and Ethics

A. Describe basic software components.

  1. Describe operating systems.
  2. Describe high-level and machine languages.
  3. Describe compilers.

B. Examine ethics.

  1. Examine ethics in the context of software development.
  2. Examine the impact of ethics violations on software developers.
  3. Examine the impact of ethics violations on software users.

II. Problem-Solving in Software Development

A. Define the problem.

B. Develop a solution.

  1. Utilize top-down design.
  2. Consider previous problems and solutions.
  3. Reuse pertinent algorithms.
  4. Represent algorithms with pseudo-code.
  5. Identify input, output, processing and modules.

C. Code the solution.

D. Test the solution.

  1. Perform unit and integration testing.
  2. Select appropriate test data.
  3. Trace code by hand (desk-checking) and with a debugger.
  4. Evaluate code efficiency and simplicity.

III. Fundamental Programming Features

A. Declare and initialize variables and constants.

B. Use built-in operators to create expressions and statements.

  1. Write assignment statements.
  2. Create expressions with arithmetic, relational and logical operators.
  3. Use the conditional (ternary) operator.
  4. Evaluate expressions using rules of operator precedence.
  5. Compare strings and numeric types.
  6. Dereference and assign values to pointers.

C. Perform input and output.

  1. Retrieve data from the keyboard.
  2. Retrieve data from input files.
  3. Write data to the console window.
  4. Write data to output files.

D. Call built-in mathematical functions.

E. Implement type-casting.

F. Control program flow.

  1. Implement selection statements.

a. Write code with if, else and else-if statements.

b. Use switch statements.

c. Write nested selection statements.

  1. Implement repetition statements

a. Write while, for and do loops.

b. Create nested loops.

c. Analyze break and continue semantics.

G. Trap errors using selection or repetition.

IV. Procedures

A. Define and call functions with void and non-void return values.

B. Declare functions (prototyping).

C. Implement pass-by-value and pass-by-reference parameters.

D. Differentiate between actual and formal parameters.

E. Analyze and write elementary recursive code.

F. Analyze variable scope and lifetime.

G. Implement static variables.

V. Fundamental Data Structures and Algorithms

A. Implement single dimensional arrays.

  1. Implement an array of integers.
  2. Implement null-terminated strings.

B. Implement two-dimensional arrays.

C. Implement dynamic arrays.

  1. Use new and delete to manage memory.
  2. Declare pointers.

D. Search arrays.

  1. Implement sequential search.
  2. Implement binary search.

E. Sort arrays.

  1. Sort data using bubble sort.
  2. Sort data using selection sort.
  3. Sort data using insertion sort.

F. Implement structures.

G. Implement an array of structures.

VI. Object-oriented Programming

A. Write code using the built-in string class and associated methods.

B. Write code using the built-in vector class and associated methods.

C. Implement encapsulation and data abstraction by writing user-defined classes.

D. Differentiate between private and public access modifiers.

E. Hide member data.

F. Write accessors, mutators and other member functions that process member data.

G. Write code that utilizes objects.

H. Implement an array of objects.

VII. Code Standards

A. Create descriptive identifiers according to language naming conventions.

B. Write structured and readable code.

C. Create documentation.

VIII. Professional Development Environment

A. Write code using a professional, integrated development environment (IDE).

B. Utilize key editor features.

C. Debug code using the integrated debugger.

D. Include and use standard libraries.


4. Reading

4.1. Unit 00: Welcome and setup

4.1.1. Welcome!

It feels weird to start a collection of notes (or a "textbook") without some sort of welcome, though at the same time I know that people are probably not going to read the introduction (Unless I put some cute art and interesting footnotes, maybe.) I think that I will welcome you to my notes by addressing anxiety.


  1. Belonging

    Unfortunately there is a lot of bias in STEM fields and over decades there has been a narrative that computer science is for a certain type of person - antisocial, nerdy, people who started coding when they were 10 years old.

    Because of this, a lot of people who don't fit this description can be hesitant to get into computers or programming because they don't see people like themselves in media portrayals. Or perhaps previous professors or peers have acted like you're not a real programmer if you didn't start programming as a child

    If you want to learn about coding, then you belong here.

    There are no prerequisites.

    I will say from my own experience, I know developers who fell in love with programming by accident as an adult after having to take a computer class for a different degree. I know developers who are into all sorts of sports, or into photography, or into fashion. There is no specific "type" of programmer. You can be any religion, any gender, any color, from any country, and be a programmer.


    Figure 1: Don't be like Gatekeeper Baby. You can begin coding at any age!


  2. Challenge

    Programming can be hard sometimes. There are many aspects of learning to write software (or websites, apps, games, etc.) and you will get better at it with practice and with time. But I completely understand the feeling of hitting your head against a wall wondering why won't this work?! and even wondering am I cut out for this?! - Yes, you are.

    I will tell you right now, I have cried over programming assignments, over work, over software. I have taken my laptop with me to a family holiday celebration because I couldn't figure out this program and I had to get it done!!

    All developers struggle. Software is a really unique field. It's very intangible, and there are lots of programming languages, and all sorts of tools, and various techniques. Nobody knows everything, and there's always more to learn.

    Just because something is hard doesn't mean that it is impossible.


    It's completely natural to hit roadblocks. To have to step away from your program and come back to it later with a clear head. It's natural to be confused. It's natural to not know.

    But some skills you will learn to make this process smoother are how to plan out your programs, test and verify your programs, how to phrase what you don't know as a question, how to ask for help. These are all skills that you will build up over time. Even if it feels like you're not making progress, I promise that you are, and hopefully at the end of our class you can look back to the start of it and realize how much you've learned and grown.

  3. Learning

    First and foremost, I am here to help you learn.

    My teaching style is influenced on all my experiences throughout my learning career, my software engineer career, and my teaching career.

    I have personally met teachers who have tried to scare me away from computers, I've had teachers who really encouraged me, I've had teachers who barely cared, I've had teachers who made class really fun and engaging.

    I've worked professionally in software and web development, and independently making apps and video games. I know what it's like to apply for jobs and work with teams of people and experience a software's development throughout its lifecycle.

    And as a teacher I'm always trying to improve my classes - making the learning resources easily available and accessible, making assignments help build up your knowledge of the topics, trying to give feedback to help you design and write good programs.

    As a teacher, I am not here to trick you with silly questions or decide whether you're a real programmer or not; I am here to help guide you to learn about programming, learn about design, learn about testing, and learn how to teach yourself.



  4. Roadmap


    When you're just starting out, it can be hard to know what all you're going to be learning about. I have certainly read course descriptions and just thought to myself "I have no idea what any of that meant, but it's required for my degree, so I guess I'm taking it!"

    Here's kind of my mental map of how the courses I teach work:

    CS 200: Concepts of Programming with C++
    You're learning the language. Think of it like actually learning a human language; I'm teaching you words and the grammar, and at first you're just parroting what I say, but with practice you'll be able to build your own sentences.
    CS 235 Object-Oriented Programming with C++
    You're learning more about software development practices, design, testing, as well as more advanced object oriented concepts.
    CS 250 Basic Data Structures with C++
    You're learning about data, how to store data, how to assess how efficient algorithms are. Data data data.

    In addition to learning about the language itself, I also try to sprinkle in other things I've learned from experience that I think you should know as a software developer (or someone who codes for whatever reason), like

    • How do you validate that what you wrote actually works? (Spoilers: How to write tests, both manual and automated.)
    • What tools can you use to make your programming life easier? (And are used in the professional world?)
    • How do you design a solution given just some requirements?
    • How do you network in the tech field?
    • How do you find jobs?
    • What are some issues facing tech fields today?

    Something to keep in mind is that, if you're studying Computer Science as a degree (e.g., my Bachelor's degree is in Computer Science), technically that field is about "how do computers work?", not about "how do I write software good?" but I still find these topics important to go over.


    That's all I can really think of to write here. If you have any questions, let me know. Maybe I'll add on here.


  5. What is this weird webpage/"book"?

    In the past I've had all my course content available on the web on separate webpages. However, maintaining the HTML, CSS, and JS for this over time is cumbersome. Throughout 2023 I've been adapting my course content to emacs orgmode documents, which allows me to export the course content to HTML and PDF files. I have a few goals with this:

    1. All course information is in one singular place
    2. At the end of the semester, you can download the entire course's "stuff" in a single PDF file for easy referencing later on
    3. Hopefully throughout this semester I'll get everything "moved over" to orgmode, and in Summer/Fall 2024 I can have a physical textbook printed for the courses, which students can use and take notes in so as to have most of their course stuff in one place as well
    4. It's important to me to make sure that you have access to the course content even once you're not my student anymore - this resource is available publicly online, whether you're in the course or not. You can always reference it later.

    I know a lot of text can be intimidating at first, but hopefully it will be less intimidating as the semester goes and we learn our way around this page.



4.1.2. Tools for software development

  1. What kind of tools are needed to make programs?


    To write software, we need to write instructions - the program source code is the list of instructions. This means we need some kind of text editor program. To turn the program instructions into stuff humans can read into stuff computers can read (that is, binary, or an executable file), we need a compiler program.

    These are the two things that are needed at minimum, but there are plenty more tools to help us be more effective at our jobs. For instance, if you use the default "Notepad" on Windows it's going to be a bunch of black text on a white background. If you use a text editor meant for code, however, you'll get syntax highlighting - which color-codes different commands, helping us read the code more clearly.

    \begin{lstlisting}[style=cpp] #include using namespace std; int main() { cout << "Hello, world!" << endl; return 0; } \end{lstlisting}

    Since we'll be writing a lot of different programs and referring back to these programs throughout the semester you will also want to keep things organized and backed up. There is special software that software developers use to keep track of their code changes over time, called source control or version control. We will be using the Git version control system in this course, though we are going to stick to the web interface view for this introductory course.



4.2. Unit 01: Tech Literacy: Exploring computers

In this class we will be learning to write C++ programs for a computer, but knowing why we do things in certain ways, or why things work the way they do, often boils down to how the computer itself works. I would like to try to give you some context about computers so you will be better prepared to understand the topics we cover in the future.


4.2.1. Computing tools

Throughout history humans have needed to do math and store records.


Figure 2: Cuneiform tablet: inventory account, Ebabbar archive, Babylonian, ca. 7th–6th century BCE, Public Doamin, from https://www.metmuseum.org/art/collection/search/321707

The earliest known writing system, Cuneiform, was used to store information about inventory - how much of each thing do you have? How much copper did you buy from Ea Nasir? And so on. Cuneiform tablets were a form of long-term storage of records.

However, when someone needed to do math, they wouldn't write it out on a tablet like we do on notebook paper. The Abacus was used to do computations. This way you could have temporary data you work through, such as "add this", "subtract that", on your way to get the final value.

This is what we still use computers for today - long term storage, such as storing data in a database, and short-term processing, such as calculating all the items in your shopping cart, applying shipping and tax, and returning the resulting cost.


4.2.2. User interface


Figure 3: LEFT: Image of the TRS-80 Model I, image by Tim Colegrove/Pittigrilli, from https://en.wikipedia.org/wiki/Commodore_PET , RIGHT: IBM PC running GEM, image by Rolf Hartmann, from https://en.wikipedia.org/wiki/History_of_the_graphical_user_interface

Early computers did not have computer monitors like we use today, and didn't even use keyboards hooked up directly to the computers. Instead, to create a program for an old mainframe, you'd have to sit down at a punchcard typewriter, type out your program on punchcards, then feed those cards into the computer. Your program's output could be in the form of more punchcards, a sheet of printed out paper, paper tape, and other things.

How we "talk" to a computer is referred to as Input, and how we receive a response from a computer is known as Output. Together, it can be thought of as an Interface.


Eventually, using a keyboard and a monitor became a standard method for interacting with computers, especially with the personal computers in the 1970s-1980s. Even the computer Mouse wasn't common until later on. These computers had a small amount of RAM for working-memory, and would use floppy disks or casette tapes as long-term storage.

These systems were heavily text-based, though could draw rudimentary graphics - usually for video games. These computers had a Command Line Interface, or CLI.


Graphical User Interfaces (aka GUIs) became more mainstream in the 1990s, especially as the computer Mouse took off. As use of GUIs continued, a type of standard evolved alongside it for how we interact - single-click, double-click, click and drag, and so on. Similarly, a unique interface "language" has also been developed for mobile phones. We don't usually "double-tap" the screen, but a single-tap, a press-and-hold, or even swiping in different directions all map to certain commands.


User Interfaces for our programs

In this course we are focusing on Command Line Interfaces (CLI), text based interfaces where the interaction is mostly based around keyboard input from the user and text output to the console. This helps us focus on learning about the language itself, rather than getting bogged down in markup languages to build a GUI, design, and the process of hooking up our "back end" (processing data) to the "front end" (nice buttons, images, textboxes, etc.)

CLI programs are still created and used today, but usually by more technical people - the average layperson tends to work exclusively in the GUI.


🧠Tech Literacy discussion: Exploring software (U02.TEC.202406CS200):

  • Some examples of user input interfaces are the keyboard and mouse of a computer. What other ways can you think of to interact with a computer, giving it input?
  • Some examples of program output interfaces are displaying text to the monitor or playing a sound effect. What other ways can you think of that a computer gives you a response, as output?


4.2.3. Long-term storage: The Filesystem


Whether we're working on our phone, our computer, or a website that stores data in "the cloud" (aka someone else's computer), data that we want to preserve between runs of the program (or even after we shut off and turn on our computer again) goes in long-term storage. This includes information our program processes, but also the program itself - we install software, it is saved on the system's hard-drive, and we can use it when we want without re-installing it each time.

As we work on our programs this semester we will be storing our source code files on our computers (and on the GitLab servers :), and our programs will also work with reading in and writing out to files, like text files, HTML files, or CSV spreadsheets. Knowing how to navigate your system's filesystem is important.


  1. Files and Folders

    Our computers organize things into Files and Folders. Folders (aka "directories") represent locations. Folders can contain other folders ("subfolders") or files. Files are all the rest - our text files, images, music, videos, and so on. The actual data the computer stores, that we can read and write.

    Folders and files both have names, but files often also have extensions. This is the information after the "." that specifies what kind of file it is:

    File name File type
    readme.txt Plain-text file
    photo10.jpg jpeg photo file
    song.mp3 mp3 audio file
    video.mp4 mp4 video file
    homework.docx Microsoft Word file
    unit01.zip Compressed (zipped) file

    In Windows it often turns off extensions by default. I would recommend turning on extensions to make differentiating your course project files more easy. Check the Reference portion of the textbook for steps (search for "Turning on viewing file extensions in Windows").


  2. Paths

    Each Operating System might store their filesystems differently, but a lot of the concepts are the same. A filesystem is conceptually based off of paper folders (like in a file cabinet) where you have a lot of folders labeled, and each folder can contain multiple files. If we didn't come up with some way to organize the data on our computers it would be difficult to find everything in the jumbled mess.

    Our system has some sort of root directory (or folder), like the roots of a tree - the starting point. In Windows, it's often your C:\ drive. In Linux and Mac, it's usually just labeled /. Often there are system folders in the root directory, and then we have some kind of "home" or "my documents" folder set aside for us to store our files in.

    In a path, each folder is separated by a slash - in Windows, it's backslash (\) and in Mac and Linux it's forwardslash (/).

    • Windows user directory: C:\Users\USERNAME\Documents
    • Linux/Mac user directory: /home/USERNAME/

    As we navigate a filesystem, going into a subfolder will build up the directory path you're currently in. There is an "up" button on most filesystem explorers as well, where the "up" command takes you out of your current folder and back into its parent folder.


    1. Absolute paths and relative paths

      When we type out a fullpath, such as


      this is known as an absolute path. While we're working within our programs, we can also use relative paths to locate nearby files.


      Example: Homework

      Let's say your CS 200 directory looks like this:

       - week1/
          - laba.cpp
          - labb.cpp
          - myname.txt
          - project1/
              - data/
                 - savegame.txt
              - hello.txt
              - program.cpp

      Our program is the program.cpp source file.

      • If we told our program to open hello.txt, we would retrieve the hello.txt file in the same folder (project1/), without having to type the entire absolute path


      • If we want to open the savegame.txt file, we would specify the subfolder it is in as well as the filename: Program, open data/savegame.txt.
      • If we wanted to access a file in the folder above the project1 folder, we could use the ../ relative path to go "up" one folder. If our program wanted to load "myname.txt", we could reference it as ../myname.txt.




4.2.4. Short-term processing: The CPU and RAM


Our program itself and the data it reads and writes all are stored on the hard-drive in long-term storage, but long term storage is slow. When we're actively working with something it needs to be loaded into a faster type of memory. RAM (Random Access Memory) is the short-term working memory that a computer uses. RAM is plugged into the computer's motherboard directly, while hard drives are still usually hooked up with some kind of cable, which slows down its access (input/output) speed.

While we're creating our programs, any time we create a variable it will have a block of space set in RAM (well, the Operating System virtualizes it… we're not accessing the RAM directly, but we can think of it that way for now).

While we don't have to worry about loading our program into RAM - the operating system handles that and a lot of other things for us - we will have a chance to look at memory addresses and how we can allocate memory for additional data. Memory management and allocating memory for variables is a big part of core computer science classes.


Figure 4: Block diagram of a basic uniprocessor-CPU computer. Black lines indicate data flow, whereas red lines indicate control flow; arrows indicate flow directions., image by Lambtron, from https://en.wikipedia.org/wiki/Central_processing_unit

While the RAM stores the program's data, the CPU (Central Processing Unit) handles doing the math operations. We're not going to go into how CPUs work, though if you take a Computer Architecture class you will learn about how they work and how they're designed. The main gist here is that the CPU takes in inputs, does computations, and returns outputs.

4.2.5. The Operating System


Figure 5: Screenshot of the Windows 3.0 workspace, image by Tyomitch, from https://en.wikipedia.org/wiki/Windows_3.0

All of our modern software runs on top of some Operating System, whether that's something like Android on a phone, Windows on a computer, or whatever kind of operating system your game console runs on top of. The Operating System is a special type of software that acts as an intermediary between your computer's hardware and its software. It helps us so that we don't have to know exactly how the wifi works, or exactly how to work with xyz brand of keyboard - the Operating System uses programs called drivers to work with those things itself.

Operating Systems you might have used are: Windows, Linux, Mac, iOS, Android. If you're older, you might have used DOS as well! (I used DOS in the 1990s to load some of my video games, mostly.)


The Software we run are the programs or apps themselves: Our web browser (Firefox, Chrome), the bank app we use, a document writer (MS Word, LibreOffice). Software is often built to be packaged and shared or sold to other people, though you can also write our own little software utilities for personal use once you have enough experience.


🧠Tech Literacy discussion: Exploring software (U02.TEC.202406CS200):

  • Give an example of a phone app that you use.
  • Give an example of desktop software that you use.
  • What kind of program would you like to write, if you can think of anything?


4.2.6. What is Software?

A computer needs to be told how to do everything. If you were writing a program totally from scratch, you would have to tell it how to load a bitmap file, how to draw a rectangle, how to detect mouse clicks, how to animate a transition, and everything else. However, software has been evolving for decades now, and a lot of these features are already implemented in libraries. Libraries are sets of pre-written code meant for other programs to import and use.


With some of the first computers, the only commands you could program in directly mapped to the CPU on the machine. This type of code was called machine code or assembly. Later, developers such as Grace Hopper worked on ways to write code that lets you fit multiple machine-code-pieces into one command that was more human-readable, leading to early languages like COBOL. Many of these "higher-level" languages (higher-level meaning further from the hardware; more abstracted) eventually will get turned into machine code through a process called compiling.


Example: Displaying "Hello, world!" output in C++:

\begin{lstlisting}[style=cpp] #include // Load input/output library using namespace std; // C++ standard libraries int main() { // Display message to screen cout << "Hello, world!" << endl; // Quit return 0; } \end{lstlisting}


Example: Displaying "Hello, world!" output in MIPS Assembly:

\begin{lstlisting}[style=cpp] .data Hello: .asciiz "\n Hello, world!" .globl main .text main: # load syscall; address of string (set up for string output) li $v0, 4 # load address of string into parameter $a0 la $a0, Hello # display syscall \end{lstlisting}


Compiled languages aren't the only variety - Java runs in a Java Virtual Machine, and Python is a scripting language that runs via a Python executable. But we're focusing on C++ here. – The point is, modern software is built on top of many layers: high-level languages that compile down to machine code, pre-written libraries of code that handle common features for the programmers so they don't have to reinvent the wheel.


  1. How programs work

    Since a computer needs to be told how to do everything, a computer program is a list of very specific instructions on how to execute some task (or tasks, for larger programs).


    Figure 6: Inputs and Outputs


    1. Inputs

      Some programs don't take any input and just run a set of pre-defined instructions. Most programs do take some form of input, however, whether that's when the program first starts up or during its runtime.

      Inputs could include things like passing in a filename to a program (e.g., please open this file) or other pieces of data, or getting keyboard input, gamepad input, mouse input, touch screen input, or receiving signals via the network or internet.


    2. Outputs

      Programs also often will return some form of output, but this is also optional. If a program doesn't return output, maybe the user just wants to tell the program to do a job, but doesn't need confirmation that the job was done (these are usually called background processes).

      Outputs could be something like displaying a message box, changing text on the screen, playing a sound, or writing out a text file.


      Figure 7: Variables


    3. Variables

      Our program may also use variables to store data during its execution. Variables are locations in memory (RAM) where we can store numbers, text, or more complex objects like an image. We give variables a name to reference it by, such as userName or cartTotal, and we can do math operations on it, as well as write it to the screen or read new values into it from the user.


    4. Branching and looping


      Figure 8: A flowchart diagram of a "decision diamond" that branches in one of two directions.

      We can also change the instructions our program runs based on some condition we set. For example, if bankBalance < 0 then maybe we display an error message. Otherwise, we can withdraw some amount of money from the bankBalance.



      Figure 9: A flowchart diagram of a "decision diamond" that loops back on itself.

      We may also want to take advantage of looping to do a set of instructions repeatedly, possibly with some variables changing each time through the loop. An example for this could be to loop over all of a student's assignmentGrades, adding up all the points so we can find an average.


  2. Example programs
    1. Area calculator

      This program asks the user to enter a width and a height and then calculate the area of the rectangle with the given information.

      \begin{lstlisting}[style=cpp] cout << "Width: "; // Display message cin >> width; // Get user input cout << "Height: "; // Display message cin >> height; // Get user input area = width * height; // Do math cout << "Area: " << area << endl; \end{lstlisting}


    2. ATM - Withdrawing money

      This program asks the user how much they'd like to withdraw from their account. If the withdraw amount is more than their account balance, then an error message is displayed. Otherwise, the amount is withdrawn from their bank account.

      \begin{lstlisting}[style=cpp] cout << "Withdraw: "; // Display message cin >> withdrawAmount; // Get user input if ( withdrawAmount > bankBalance ) cout << "Error! Not enough money." << endl; else bankBalance = bankBalance - withdrawAmount; \end{lstlisting}


  3. C++ Programs

    Each programming language is a little different in how it looks, but whether you're using C++, Java, C#, Python, or many other languages, you'll still encounter branching with if statements, looping, functions, and classes (though older languages may not have classes at all, like C!).

    1. main(): The starting point

      With C++, Java, and C#, programs must begin in a function called `main()`. The compiler (that turns the program into machine code) is always expecting `main()` to be there and to begin running the program at the top of it.


    2. Basic C++ syntax

      In C++, Java, C#, and other C-like languages, there are some basic rules of syntax you should know about:

      1. Lines of code:

        A code statement ends with a semi-colon. Statements are single commands like cout (console-out) to display text to the output, cin (console-in) to read input from the keyboard, declaring variables, assigning variables, or doing math operations.


      2. Variable names:

        There are some rules for naming variables in C++. Generally, you can use any upper or lower case letters, numbers, and underscores in variable names - no spaces allowed. Beyond that, variables cannot begin with a number, and you cannot use a keyword (such as if) as a variable name.


      3. Code blocks:

        There are certain types of instructions that contain additional code. If statements, for example, contain a set of instructions to execute only if its condition evaluates to `true`. Any time an instruction contains other instructions, we use opening and closing curly braces {} to contain this internal code. Additionally, with these instructions, they do not end with semicolons.



        It is often useful to add comments to programs to specify what is going on in the code. There are two ways to add comments in C++. Generally, you can use any upper or lower case letters, numbers, and underscores in variable names - no spaces allowed. Beyond that, variables cannot begin with a number, and you cannot use a keyword (such as if) as a variable name.


      5. Whitespace and code cleanliness:

        Generally, C++ doesn't care if multiple commands are on one line or several lines. The compiler is going to compile it all either way. You should, however, care about the code's readability to humans. Add enough new lines to separate sections of a program, use consistent indentation, and give variables descriptive names.


        When writing code inside of a code block, you should always tab forward internal code by one tab:

        \begin{lstlisting}[style=cpp] if ( order == "dessert" ) { // One tab forward cout << "Order: dessert" << endl; if ( have_cake ) { // One more tab forward cout << "You get cake!"; } else { // One more tab forward cout << "Sorry, we're out of dessert!"; } } \end{lstlisting}


4.2.7. Diagnosing, testing, and debugging


Software is an amorphous, intangible thing of arbitrary complexity. It's bad enough when you're working alone, but once you get other people involved at varying skill levels (and varying levels of writing clean code), the amount of potential issues can quickly skyrocket.

There are techniques to writing software that can help you validate your own logic and check for errors before they occur, as well as tools to help you diagnose and debug issues, as well as error messages to also help give hints to what's going wrong. All of these things are important to becoming a good software developer.


  1. Syntax errors

    The best type of error you can get is a syntax error, even though it may feel bad to get them. Syntax errors are when you have a typo or have otherwise miswritten a statement in the code, and the compiler doesn't know what to do with it. It will then display a build error telling you what it needs. Diagnosing syntax error messages can be confusing at first: often the compiler doesn't know exactly what's wrong, just what it's expecting. But, the good thing about syntax errors is that your program won't run if it can't build - that means you must fix these errors before continuing. It also means that these errors can't just be hidden in the code, like other error types.


  2. Logic errors

    Another type of error that's much harder to track down are logic errors. Logic errors can be errors in formulas, bad if statement conditions, or other things that don't do what the programmer was intending to do (again, either because of a typo, or not quite understanding the program flow, or for other reasons). Logic errors don't show up in the error list, but can cause your program to crash down the line - or worse, never crash but create bad output. Because it's not crashing, you may assume everything is working fine, but incorrect output can cause problems.


  3. Runtime errors

    When a logic error causes the program to crash while it's running, it is called a runtime error.



  4. Testing

    Programs need to be tested. Starting off, you will probably be manually running the program, entering inputs, and checking outputs. However, this gets tedious after a while and you'll probably start entering gibberish as inputs and assuming everything works if it outputs something. Manual testing is good to do, but it is easy to become sloppy. You can also write code to automatically test certain things for you. This will become more relevant to us once we're working with functions in C++.

    The main idea behind testing is that programs or functions will be taking some sort of inputs, and given those inputs you have some expected outputs or results. If the actual outputs don't match the expected outputs, then there is something wrong.

    We will cover testing techniques more later on.


  5. Coding techniques for newbies

    When you're first starting with C++, it can feel like your code just never works. It can be good to adopt a few of these practices while you're still new, to minimize errors and frustration:

    • Compile often: Get into the habit of using keyboard shortcuts to build your code after every few lines - especially when you're first starting out. If you write two lines of code and get a syntax error, it's much easier to diagnose than if you write a whole program and then build.
    • Search for syntax error messages: Most of these messages have been posted about before on boards like Stack Overflow. Reading through these can help give you insight into what the error means, and common ways to fix them.
    • Comment things out: If you have a lot of code but can't get it compiling and aren't sure what to do, you can comment out large chunks of the program until it builds again. Then, bit by bit, uncomment out different regions until you find what's causing the build error.

    These practices can help you become a more efficient and effective programmer, especially when you're first starting out. Debugging and testing are essential skills for any programmer, and learning them early can save you a lot of time and frustration in the long run.


4.3. Unit 02: C++: Variables, pointers, input, and output

4.3.1. main(): The starting function

The bare-minimum C++ program looks like this:

\begin{lstlisting}[style=cpp] int main() { return 0; } \end{lstlisting}

No matter what all is in your program, your compiler is going to expect that a main function exists, and this function acts as the starting point of a C++ program.


A compiler is a program that converts your code (such as C++ code) into an executable file that your computer can run.


The opening curly-brace { and closing curly-brace } denote the start and end of the main function. The curly-braces and any code within is known as a code-block. Program instructions will go within this code-block.


At the end of the main function we have return 0;. In this context, it means "return (exit) the program with a status of 0", with that basically meaning "return with no errors". If you ran into an error while the program was running, you might do something like return 123; instead, to mark the area with an "error code" (123), which you can then find in the code.


For our programs starting off, we will be putting our instruction code after the opening curly-brace { and before the return 0;, but the code given above is the absolute, bare-minimum required to write a C++ program.


C++ source code files will end in the extension ".cpp" on your computer. A file extension helps you and the computer identify what a file does and how to open it, like a ".txt" file can be opened in a text editor like Notepad.


For information on how to create a project and build and run your code, check the "Reference" section, where steps are given.


4.3.2. Variables: Storing our data


  1. What are variables?


    Variables are named locations where we can store information.

    We use variables in programming as places to temporarily store data so that we can manipulate that data. We can have the user write to it via the keyboard, we can use files to write data to variables, we can do math operations or modify these variables, and we can print* them back out to the screen or a text file.(*Printing here meaning "display on the screen"; not to a printer.)


    When we're writing programs in C++, we need to tell our program what the data type of each variable is, and give each variable a variable name (aka identifier). When a variable is declared, a space in RAM is allocated to that variable and it can store its data there. That data can be manipulated or overwritten later as needed in the program.


    Some examples of things we might store as variables:

    • A student's information:
      • string studentName, the name of a student
      • float studentGpa, the GPA of that student
      • int creditHoursCompleted, the total amount of credit hours the student has completed
      • bool activeStudent, whether the student is an active student or not (e.g., graduated?)
    • A store website's item listing:
      • string name, the name of the product
      • float price, the price of the product
      • int quantity, how much of this product is in stock


  2. Data types

    In C++, when we want to create a variable we need to tell the compiler what the data type of the variable is. Data types specify what is stored in the variable (whole numbers? numbers with decimal values? text? true/false values?). Each data type takes up a different amount of space in memory.

    Data type Values Size Example code
    char single symbols - letters, numbers, anything 1 byte char currency = '$';
    boolean true or false 1 byte bool savedGame = false;
    integer whole numbers 4 bytes int age = 100;
    float numbers w/ decimals 4 bytes float price = 9.95;
    double numbers w/ decimals 8 bytes double price = 1.95;
    string any text, numbers, symbols, any length 4 bytes string password = "123secure";
    • Floats and doubles both store numbers with fractional (decimal) parts, but a double takes up double the memory in RAM, allowing to store more accurate fractional amounts. A float has 6 to 9 digits of precision and a double has 15 to 18 digits of precision. (From https://www.learncpp.com/cpp-tutorial/floating-point-numbers/)
    • Boolean data types store true and false values, but will also accept integer values when assigned. It will convert a value of 0 to false and any other number to true.
    • String variables' values must be written within double quotes "Hello!"
    • Character variables' values must be written within single quotes 'Z'


    1. Additional information: Unsigned data types

      Sometimes it doesn't make sense to store negative values in a variable - such as speed (which isn't directional, like velocity), the size of a list (can't have negative items), or measurement (can't have negative width). You can mark a variable as unsigned to essentially double its range (by getting rid of the negative side of values). For instance, a normal int can store values from -2,147,483,648 to 2,147,483,647, but if you mark it as unsigned, then your range is 0 to 4,294,967,295.


  3. Declaring variables and assigning values to variables
    1. Variable declaration

      When we're declaring a variable, it needs to follow one of these formats:

      Declaration forms

      • DATATYPE VAR1, VAR2, VAR3;

      The data type goes first, then the variable name/identifier, and if you'd like, you can also assign a value during the same step (though this is not required). Once a variable has been declared, you don't need to declare it again. This means you don't need to re-specify its data type when you're using it. Just address the variable by its name, and that's all.


      Example: Code that uses integers to figure out how many candies each kid should get:

      \begin{lstlisting}[style=cpp] // Declaring variables and assigning values int totalCandies{10}; int totalKids{5}; int candiesPerKid{totalCandies / totalKids}; // Reusing the same variables later on totalCandies = 100; totalKids = 10; candiesPerKid = totalCandies / totalKids; \end{lstlisting}


      Example: Code to display the price plus tax to the user:

      \begin{lstlisting}[style=cpp] float price = 9.99; float tax = 0.11; // Text output to the screen. Can do math within! cout << "Please pay " << (price + price * tax); \end{lstlisting}


      1. Additional information: Modern C++: auto

        In C++11 (from 2011) and later, you can use the keyword auto as the "data type" in your variable declaration that includes an assignment statement. When you use auto, it uses the assigned value to automatically figure out the variable's data type, so you don't have to explicitly define it:

        \begin{lstlisting}[style=cpp] auto price = 9.99; // it's a double! auto price2 = 2.95f; // it's a float! auto player = '@'; // it's a char! auto amount = 20; // it's an int! \end{lstlisting}


    2. Variable assignment

      Assignment forms

      • Stores the LITERAL value in VARIABLENAME:


      • Copies the value from VARIABLENAME2 to VARIABLENAME1.:


      When assigning a value to a variable, the variable being assigned to always goes on the left-hand side ("LHS") of the equal sign =. The = sign is known here as the assignment operator.


      The item on the right-hand side ("RHS") will be the value stored in the variable specified on the LHS. This can be a literal (a hard-coded value) or it can be a different variable of the same data type, whose value you want to copy over.


      Example: Assigning literal values to variables:

      \begin{lstlisting}[style=cpp] price = 9.99; // 9.99 is a float literal state = "Kansas"; // "Kansas" is a string literal operation = '+'; // '+' is a char literal \end{lstlisting}


      Example: Copying student3's value to the bestStudent variable:

      \begin{lstlisting}[style=cpp] // Declare and initialize our variables string student1 = "Hikaru"; string student2 = "Umi"; string student3 = "Fuu"; string bestStudent; // Assignment statement bestStudent = student3; \end{lstlisting}



    3. Variable initialization

      When we declare a variable and give it a value in the same line of code, that is called initialization. The equal sign can be used in this regard:

      \begin{lstlisting}[style=cpp] string productName = "Candybar"; float productPrice = 3.25; \end{lstlisting}


      But with more modern C++, it's recommended that we use braced initialization:

      \begin{lstlisting}[style=cpp] string productName{ "Candybar" }; float productPrice{ 3.25 }; \end{lstlisting}


      You might see both of these ways used to initialize variables in starter code.



      If a variable is not initialized with some value, it will have some garbage value assigned to it - whatever was left over in the memory space where it was created. This data isn't useful to us, and usually shows up as random large numbers (12734827), so it's good to make sure to initialize your variables!


    4. Named constants

      Whenever you find yourself using a literal value in your assignment statements, you may want to think about whether you should replace it with a named constant instead.

      Declaration form

      • const CONSTNAME = LITERAL;

      A named constant looks like a variable when you declare it, but it also has the keyword const - meaning that the value can't change after its declaration.


      Let's say you wrote a program and hard-coded the tax rate:

      \begin{lstlisting}[style=cpp] // Somewhere in the code... totalPrice = cartTotal + ( cartTotal * 0.0948 ); // Somewhere else in the code... cout << 0.0948 << " sales tax" << endl; \end{lstlisting}


      Then the tax rate changes later on. You would have to go into your program and search for "0.0948" and update all those places! Instead, it would have been easier to assign the tax rate ONCE to a named constant and referred to that instead:

      \begin{lstlisting}[style=cpp] // Beginning of program somewhere... const SALES_TAX = 0.0948; // Somewhere in the code... totalPrice = cartTotal + (cartTotal * SALES_TAX); // Somewhere else in the code... cout << SALES_TAX << " sales tax" << endl; \end{lstlisting}


      If you ever find yourself using the same literal multiple times in your program, then perhaps consider replacing it with a named constant.


  4. Naming conventions

    While you can generally name a variable whatever you'd like, you still need to adhere to the syntax rules of the C++ language. In particular:

    • Names can only contain letters (upper- and lower-case), numbers, and underscores.
    • Spaces are not allowed in a variable name!
    • Names cannot start with a number.
    • A name cannot be a keyword in C++, a name reserved for something else in the language, such as void, if, int, etc.

    There are also naming conventions used so that variables (and later on functions and structs/classes) have a consistent naming scheme:

    • Variables:
      • One common style is lowerFirstLetterThenUpperCase for variable names - this is called Camel Case.
      • Another style you might see in C++ code is all_lower_with_underscores.
      • You might see both of these styles in my starter code or examples, but I try to stick to one style for a program. You should also choose one and stay consistent in each program.
    • Named constants:
      • It is customary to give your named constants names in ALL CAPS, using underscores (_) to separate words. For example: TOTAL_STUDENTS, OP_TAX_RATE, etc.


    Everything in C++ is case sensitive, which means if you name a variable username, it will be a different variable from one named userName (or if you type "userName" when the variable is called "username," the compiler will complain at you because it doesn't know what you mean).


  5. Basic operations on variables

    Now that you have variables available in your program to play with, what can you even do with them?


    1. Outputting variable values

      Using the cout (console-out) statement, you can display text to the screen with string literals:

      \begin{lstlisting}[style=cpp] cout << "Hello, world!" << endl; \end{lstlisting}


      But you can also display the values stored within variables, simply by using the variable's name:

      \begin{lstlisting}[style=cpp] cout << myUsername << endl; \end{lstlisting}


      You can also chain as many literals, variables, and commands together as long as they have the output stream operator << in-between.

      \begin{lstlisting}[style=cpp] cout << "Student: " << name << endl << "GPA: " << gpa << endl << "Year: " << year << endl << endl; \end{lstlisting}


    2. Inputting variable values

      We can use the cin (console-in) statement to get the user to enter something on the keyboard and store that data into a variable:

      \begin{lstlisting}[style=cpp] float gpa; cin >> gpa; \end{lstlisting}


      cin >> can be used on strings, but it will not read anything after a space. Instead, we use the getline function to read whole lines of text into string variables:

      \begin{lstlisting}[style=cpp] string oneLine; getline( cin, oneLine ); string oneWord; cin >> oneWord; \end{lstlisting}



      There will be more information on input and output in a later section.


    3. Math operations

      With variables with numeric data types (ints, floats, doubles), we can do arithmetic with the +, -, *, and / operators.

      \begin{lstlisting}[style=cpp] cout << "Sum: " << num1 + num2 + num3 << endl; \end{lstlisting}


      Symbol Description
      + Addition
      - Subtraction
      * Multiplication
      / Division

      Make sure to put the result somewhere! When you do a math operation and you want to use the result elsewhere in the program, make sure you're storing the result in a variable via an assignment statement! If you just do this, nothing will happen:

      \begin{lstlisting}[style=cpp] totalCats + 1; \end{lstlisting}


      You can use an assignment statement to store the result in a new variable:

      \begin{lstlisting}[style=cpp] newCatTotal = totalCats + 1; \end{lstlisting}

      Or overwrite the variable you're working with:

      \begin{lstlisting}[style=cpp] totalCats = totalCats + 1; \end{lstlisting}



    4. Compound operations:

      There are also shortcut operations you can use to quickly do some math and overwrite the original variable. This works with each of the arithmetic operations:

      \begin{lstlisting}[style=cpp] // Long way: totalCats = totalCats + 5; // Compound operation: totalCats += 5; \end{lstlisting}


    5. String operations

      Strings have some special operations you can do on them. You can also see a list of functions supported by strings here: C++ String Reference (We will cover more with strings in a later part).


      1. Concatenating strings

        You can use the + symbol to combine strings together. When used in this context, the + sign is called the concatenation operator.

        \begin{lstlisting}[style=cpp] string type = "pepperoni"; string food = "pizza"; // Creates the string "pepperoni pizza" string order = type + " " + food; \end{lstlisting}


      2. Letter-of-the-string

        You can also use the subscript operator [ ] (more on this when we cover arrays) to access a letter at some position in the string. Note that in C++, the position starts at 0, not 1.

        \begin{lstlisting}[style=cpp] string food = "pizza"; char letter1 = food[0]; // Stores 'p' char letter2 = food[1]; // Stores 'i' char letter3 = food[2]; // Stores 'z' char letter4 = food[3]; // Stores 'z' char letter5 = food[4]; // Stores 'a' \end{lstlisting}


  6. Review questions:
    1. Before a variable can be used, it must be…
    2. "LHS" stands for…
    3. "RHS" stands for…
    4. The "assignment operator" is…
    5. A "literal" is…
    6. How do you write a variable declaration?
    7. How do you write a variable initialization?
    8. How do you write a variable assignment?
    9. What does the auto keyword do?
    10. What does marking a variable unsigned mean?
    11. What does case sensitive mean?


4.3.3. Introduction to memory addresses and pointer variables


  1. Bits and Bytes

    When we declare a variable, what we're actually doing is telling the computer to set aside some memory (in RAM) to hold some information. Depending on what data type we declare, a different amount of memory will need to be reserved for that variable.

    Data type Size
    boolean 1 byte
    character 1 byte
    integer 4 bytes
    float 4 bytes
    double 8 bytes

    A bit is the smallest unit, storing just 0 or 1. A byte is a set of 8 bits. With a byte, we can store numbers from 0 to 255, for an unsigned number (only 0 and positive numbers, no negatives).


    The minimum possible value for 1 byte is 0.

    (Decimal value = \(128 \cdot 0 + 64 \cdot 0 + 32 \cdot 0 + 8 \cdot 0 + 4 \cdot 0 + 2 \cdot 0 + 1 \cdot 0\))

    place 128 64 32 16 8 4 2 1
    value 0 0 0 0 0 0 0 0


    The maximum possible value for 1 byte is 255.

    (Decimal value = \(128 \cdot 1 + 64 \cdot 1 + 32 \cdot 1 + 8 \cdot 1 + 4 \cdot 1 + 2 \cdot 1 + 1 \cdot 1\))

    place 128 64 32 16 8 4 2 1
    value 1 1 1 1 1 1 1 1


    Some data types, like a Boolean and a Character, use only 1 byte. But others, like Integers and Floats, use more. Since an integer uses 4 bytes, that means it has \(8 \cdot 4\) = 32 bits available to store data. \(2^{32} = 4,294,967,296\), so floats and integers can store this many different values. (Note that this doesn't mean that an integer goes from 0 to 4,294,967,296, because we have to account for negative values.)


  2. Memory addresses

    Whenever a variable is declared, we need space to store what its value is. We have already looked at how many bytes a data type takes up, but where is the variable's data stored? – In working memory. You can think of this as the RAM, though the Operating System interacts with the RAM and gives us a "virtual memory space" to work with. But, to keep it simple, we will think of this as the RAM.



    Each block of space in memory has a memory address, one after another…

    Bit address 0 1 2 3 4 5 6 7

    Though to the computer, it represents these addresses in binary (base 2) or hexadecimal (base 16):

    Address 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07


    Hexadecimal goes from 0 to 16, but values from 10 and up are represented with letters. This is so each "number" in the value only takes 1 character (10 is two characters: 1 and 0). So, a quick reference for hexadecimal is like this:

    Base 16 (Hex) A B C D E F
    Base 10 10 11 12 13 14 15


    Example: Variable in memory

    Let's say we're investigating some blocks of memory.

    If we declare a char, which gets 1 byte, it will take up any available memory where 8 bits are available side-by-side. Some blocks in memory might already be taken, so whatever is available will be used:

    Address Variables (BEFORE)   Address Variables (AFTER)
    0x0 (used)   0x0 (used)
    0x1 (used)   0x1 (used)
    0x2     0x2 char1
    0x3     0x3 char1
    0x4     0x4 char1
    0x5     0x5 char1
    0x6     0x6 char1
    0x7     0x7 char1
    0x8     0x8 char1
    0x9     0x9 char1
    0xA(10) (used)   0xA(10) (used)
    0xB(11) (used)   0xB(11) (used)
    0xC(12)     0xC(12)  
    0xD(13)     0xD(13)  
    0xE(14) (used)   0xE(14) (used)
    0xF(15) (used)   0xF(15) (used)


    In this case, declaring our variable,

    \begin{lstlisting}[style=cpp] char char1 = 'A'; \end{lstlisting}

    its data will be placed with its first bit at address 0x2.


    We can use the address-of operator & to see what any variable's address in memory is:

    \begin{lstlisting}[style=cpp] cout << "Value: " << char1 << "\t"; cout << "Address: " << &char1 << endl; \end{lstlisting}


    Getting the address-of a variable will return the address of its first bit, so the output here would be:

    \begin{lstlisting}[style=terminal] Value: A Address: 0x2 \end{lstlisting}

    (Again, keep in mind that the representation of addresses here is simplified.)


    Example: Variable value in memory

    We can see where the variable is stored at in memory, but let's look at how it's value will be stored as well. Given the declaration:

    \begin{lstlisting}[style=cpp] char char1 = 'A'; \end{lstlisting}

    The value of 'A' is stored in 1 byte. Technically, our computer stores the letter "uppercase A" as the number code 65. This can be converted into binary: (65)10 = 0100 0001. This is the data that would be stored in that memory address.

    Address Variables Value
    0x0 (used)  
    0x1 (used)  
    0x2 char1 0
    0x3 char1 1
    0x4 char1 0
    0x5 char1 0
    0x6 char1 0
    0x7 char1 0
    0x8 char1 0
    0x9 char1 1
    0xA(10) (used)  
    0xB(11) (used)  
    0xE(14) (used)  
    0xF(15) (used)  


    This is just a basic representation, again. One thing you'll learn more about in future Computer Science courses is endian-ness, such as whether a number has its most-significant bit on the left side or the right side. We're not worrying about that here. :)


  3. Pointer variables

    Pointer variables are another type of variable, but instead of storing a value like "ABC", 'X', 10.35, or 4, it stores a memory address instead.


    1. Pointer declaration

      When we declare a normal variable, we have to specify its data type. With a pointer variable, we specify the data type of the data it's pointing to, plus the * character (after the data type) to show that this is a pointer variable.

      Declaration forms

      • DATATYPE* PTRNAME = nullptr;
      • DATATYPE* PTRNAME{nullptr};

      The pointer variable declaration takes the same form as a normal variable's declaration except we have to put the asterisk * after the data type. The asterisk can be attached to the data type, the name, or free-standing, it doesn't really matter, but I prefer keeping it with the data type.

      Safety with pointers!

      Remember how variables in C++ store garbage in them initially? The same is true with pointers - it will store a garbage memory address. This can cause problems if we try to work with a pointer while it's storing garbage.

      To play it safe, any pointer that is not currently in use should be initialized to nullptr (or NULL if you're going back to plain old C language :).



    2. Pointer assignment

      Once we have a pointer, we can point it to the address of any variable with a matching data type. To do this, we have to use the address-of operator to access the variable's address - this is what gets stored as the pointer's value.

      Assignment forms

      • Assigning an address during declaration:

        int* ptr = &somevariable;

      • Assigning an address after declaration:

        ptr = &somevariable;


      After assigning an address to a pointer, if we cout the pointer it will display the memory address of the pointed-to variable - just like if we had used cout to display the address-of that variable.


      Example: A variable and a pointer

      \begin{lstlisting}[style=cpp] // Declare normal variable int someVariable = 100; // Declare pointer variable, // point to someVariable's address int* ptr = &someVariable; // Both show someVariable's address cout << &someVariable; cout << ptr << endl; \end{lstlisting}



    3. Dereferencing pointers to get values

      Once the pointer is pointing to the address of a variable, we can access that pointed-to variable's value by dereferencing our pointer. This gives us the ability to read the value stored at that memory address, or overwrite the value stored at that memory address. We dereference the pointer by prefixing the pointer's name with a * - again, another symbol being reused but in a different context.

      Dereference forms

      • Displaying pointed-to value:

        cout << *ptr;

      • Overwriting pointed-to value:

        *ptr = 200;

      • Overwriting pointed-to value with user input:

        cin >> *ptr;


      Example: A variable and a pointer

      \begin{lstlisting}[style=cpp] // Declare normal variable int someVariable = 100; // Declare pointer variable, // point to someVariable's address int* ptr = &someVariable; // Both show someVariable's address cout << &someVariable; cout << ptr << endl; // Both show someVariable's value cout << someVariable << endl; cout << *ptr << endl; \end{lstlisting}


  4. Pointer cheat sheet
    Declare a pointer int* ptrInt;
      float *ptrFloat;
    Assign pointer to address ptrInt = &intVar;
      ptrFloat = &floatVar;
    Dereference a pointer cout << *ptrChar;
      *ptrInt = 100;
    Assign to nullptr float *ptrFloat{nullptr};
      ptrChar = nullptr;


4.3.4. Input and output: Interacting with the user

  1. Interactivity and Output in C++

    Most programs feature interactivity in some way or another. This can involve moving a mouse around, clicking on things, tapping on a touch screen, using a gamepad's joysticks and buttons, but we'll be primarily interacting with our C++ programs through keyboard input. Feedback from our C++ programs will come in the form of text output to the screen, as we are writing terminal programs.

    \begin{lstlisting}[style=terminal] Enter number 1: 1300 Enter number 2: 37 1300 + 37 = 1337 \end{lstlisting}

    We will also delve into reading from and writing to text files (or other file formats) later on. But for now, let's focus on the terminal/console.


    "Terminal", "Console", "Bash", "Command Line" tend to be used interchangably. A terminal is a text-based interface you can use to interact with your computer. In order to start simple with introductory programming, we begin by just thinking about Command Line Interfaces and writing programs that deal with text.



  2. Outputting Information with cout

    The cout command (pronounced as "c-out" for "console-out") is used to write information to the screen. This can include outputting a string literal:

    \begin{lstlisting}[style=cpp] cout << "Hello, world!" << endl; \end{lstlisting}

    or a variable's value:

    \begin{lstlisting}[style=cpp] cout << yourName << endl; \end{lstlisting}

    or stringing multiple things together:

    \begin{lstlisting}[style=cpp] cout << "Hello, " << yourName << "!" << endl; \end{lstlisting}

    In C++, we use the output stream operator << to string together multiple items for our output.


    1. Newlines with endl

      The endl command stands for "end-line" and ensures there is a vertical space between that cout statement and the next one. For example, if we write two cout statements without endl like this:

      \begin{lstlisting}[style=cpp] cout << "Hello"; cout << "World"; \end{lstlisting}

      the output will be:

      \begin{lstlisting}[style=terminal] HelloWorld \end{lstlisting}

      If we want to separate them on two different lines, we can write:

      \begin{lstlisting}[style=cpp] cout << "Hello" << endl; cout << "World"; \end{lstlisting}

      And our output will be:

      \begin{lstlisting}[style=terminal] Hello World \end{lstlisting}

      Remember that in C++, a statement ends with a semicolon ;, so you can split your cout statement across multiple lines, as long as you're chaining items together with << and only adding a ; on the last line:

      \begin{lstlisting}[style=cpp] cout << "Name: " << name << "Age: " << age << "State: " << state << endl; \end{lstlisting}


  3. Inputting Information with cin

    When we want the user to enter a value for a variable using the keyboard, we use the cin command (pronounced as "c-in" or "console-in").

    For variables like int and float, you will use this format to store data from the keyboard into the variable:


    1. Using cin >> for variables
      \begin{lstlisting}[style=cpp] cin >> VARIABLENAME; \end{lstlisting}

      You can also chain cin statements together to read multiple values for multiple variables:

      \begin{lstlisting}[style=cpp] cin >> VARIABLENAME1 >> VARIABLENAME2 >> ETC; \end{lstlisting}


    2. Strings and cin >>

      When using cin >> with a string variable, keep in mind that it will only read until the first whitespace character, meaning it can't capture spaces or tabs. For example:

      \begin{lstlisting}[style=cpp] string name; cin >> name; \end{lstlisting}

      If you enter "Rachel Singh", name will contain "Rachel". To capture spaces, you need to use a different function.


    3. Using getline(cin, var); for Strings

      You can use the getline function to capture an entire line of text as a string. This is useful when you want to capture spaces and multiple words. For example:

      \begin{lstlisting}[style=cpp] string name; getline(cin, name); \end{lstlisting}


    4. Mixing cin >> var; and getline(cin, var);

      If you mix cin >> var; and getline(cin, var);, you might encounter issues with the input buffer. To avoid this, use cin.ignore(); before getline(cin, var); if you used cin >> var; before it.

      \begin{lstlisting}[style=cpp] int number; string text; cin >> number; cin.ignore(); getline( cin, text ); \end{lstlisting}


    5. Escape Sequences

      There are special characters, called escape sequences, that you can use in your cout statements:

      Character Description
      \n newline (equivalent to endl)
      \t tab
      \" double quote

      Example code:

      \begin{lstlisting}[style=cpp] cout << "\"hello\nworld\"" << endl; \end{lstlisting}


      \begin{lstlisting}[style=terminal] "hello world" \end{lstlisting}

      Example code:

      \begin{lstlisting}[style=cpp] cout << "A\tB\tC" << endl; cout << "1\t2\t3" << endl; \end{lstlisting}


      \begin{lstlisting}[style=terminal] A B C 1 2 3 \end{lstlisting}

      Example code:

      \begin{lstlisting}[style=cpp] cout << "He said \"Hi!\" to me!" << endl; \end{lstlisting}


      \begin{lstlisting}[style=terminal] He said "Hi!" to me! \end{lstlisting}


  4. Review questions:
    1. What is a "console" (aka "terminal")?
    2. What does "cout" stand for?
    3. What does "cin" stand for?
    4. The "endl" command is used for…
    5. The \t command is used for…
    6. The \n command is used for…
    7. The "getline" function is used for…
    8. When do you need to have cin.ignore(); in your code?


4.4. Unit 03: C++: Functions


4.4.1. Program Structure


As programs become more sophisticated and offer more features, the size of the program increases. At some point, it becomes too complicated to keep your entire program just within main(). (You could certainly do it, but maintaining it would be a nightmare!)

One of the tools we use to build modular, easier-to-read code is functions. By using functions, we can delegate tasks out to other portions of the program, passing inputs as data to the function, and receiving some kind of output as a result.


As a basic example, let's say we need to calculate square footage of a room in multiple places in a program. By making a float GetArea( float width, float length ) function. Then, we only have to implement the formula once and can use the function in every part of the program. Then, we wouldn't be copy-and-pasting the same formula over and over again in the code - which also means less likelihood of errors, and easier to update later as needed.

  1. Program flow and functions

    Whenever a function is called, the program flow is redirected into that function, running from top-to-bottom as normal (with branching and loops changing that flow). Once the function has completed, it can return some data, which is received by the call location.

    From a design standpoint, this means we can break out different parts of programs into their own sections. Each function has a name, which should be used to label what the purpose of its code is.




4.4.2. Uses of functions

  1. Functions for formulas

    In algebra, you've seen functions like this:

    \[ f(x) = 2x + 3 \]

    If you were like me in algebra, you might have thought to yourself, "That's the same as \(y = 2x + 3\), why did we replace \(y\) with \(f(x)\)?"

    The reason is that we want to write a function in terms of its input, \(x\), and its output \(f(x)\). The equation \(2x + 3\) is the function body, which specifies how we get some output given some input.

    We can use functions in programming like with math as well - defining formulas that we might need a lot - but there's more to functions than just making computations.

    Let's say we want to make our "GetArea" function in math. We would need two inputs: Width and Length, and the output would end up being the area, so maybe we would name the function \(A\). It might look like this:

    \[ A( w, l ) = w \cdot l \]

    In C++, it would look like this:

    \begin{lstlisting}[style=cpp] float Area( float width, float length ) { return width * length; } \end{lstlisting}

    (Luckily we don't have to restrict ourselves to single-letter variable and function names in C++ :)


  2. Functions to validate

    Functions can also be handy in validating data and user input, putting the validation in one place instead of having to re-implement the same checks over and over.

    For example, let's say we want to keep some variable percentage in our program betwee 0% and 100% - no negative values, nothing over 100%. We could implement a function that takes the percentage as an input, and either returns the same percentage, or 0%, or 100% as output

    \begin{lstlisting}[style=cpp] int BoundPercent( int originalPercent ) { if ( originalPercent < 0 ) { return 0; } else if ( originalPercent > 100 ) { return 100; } else { return originalPercent; } } \end{lstlisting}

    Then, anywhere in the program, we could use this function to make sure our percentages are in the right range…

    \begin{lstlisting}[style=cpp] // in main() hungerPercent = BoundPercent( hungerPercent ); healthPercent = BoundPercent( healthPercent ); happinessPercent = BoundPercent( happinessPercent ); \end{lstlisting}



  3. Functions to get input

    Getting user input is a common part of writing software, and we will usually need to validate what the user is entering prior to doing any operations on it. Let's say your program is full of numbered menus and you want to validate the user's menu choices easily. You can use a function with a while loop in it:

    \begin{lstlisting}[style=cpp] int GetUserInput( int min, int max ) { int choice; cout << "Choice: "; cin >> choice; while ( choice < min || choice > max ) { cout << "Invalid choice, try again: "; cin >> choice; } return choice; } \end{lstlisting}


    You write this function once and then you can reuse it in your entire program for all menus…

    \begin{lstlisting}[style=cpp] cout << "1. Deposit money" << endl << "2. Withdraw money" << endl << "3. View balance" << endl; choice = GetUserInput( 1, 3 ); // 1, 2, or 3 if ( choice == 1 ) { cout << "1. Checking account" << endl << "2. Savings account" << endl; choice = GetUserInput( 1, 2 ); // 1 or 2 } \end{lstlisting}


  4. Functions to output

    Functions aren't required to return data. Sometimes, you just want a function that is responsible for formatting output or displaying a menu. In this case, a function's return type can be void.

    \begin{lstlisting}[style=cpp] void DisplayStudentInfo( string name, float gpa ) { cout << "Name: " << name << "GPA: " << gpa << endl; } \end{lstlisting}

    You also aren't required to pass input to functions. In this case, the parameter list between ( ) remains empty, but the () is always required for functions:

    \begin{lstlisting}[style=cpp] void DisplayMainMenu() { cout << "1. Deposit" << endl; cout << "2. Withdraw" << endl; cout << "3. View Balance" << endl; cout << "4. Log Out" << endl; } \end{lstlisting}


  5. Other uses

    These are just some examples of why you might use functions in your programs. Anything you write in main() can go inside of a different function as well - it's just another tool for designing clean, maintanable, and readable code.



4.4.3. Anatomy of a function

  1. Function Declaration
    \begin{lstlisting}[style=cpp] float GetArea( float width, float height ); \end{lstlisting}

    Before you start using a function, you have to declare and define it… A function declaration is similar to a variable declaration - we tell the program "hey, we want to use this function, here's its name and some info about it." Declaration statements end with a semi-colon and don't contain a code block (the function body) because it's just a declaration.


    1. Function Header:

      The function header is the first line of a function, which includes the following information: return type, function name, and parameter list.

      \begin{lstlisting}[style=cpp] RETURNTYPE FUNCNAME(PARAM1TYPE PARAM1NAME, ...) \end{lstlisting}


    2. Function Return Type:

      The return type of a function specifies what kind of data is returned from this function. The return type can be any data type, or it can be void if nothing is going to be returned.


    3. Function Name:

      The function name should describe what the responsibility of the function is - what it does.


    4. Function Parameters:

      The parameters of a function are a list of input variables that are expected to be passed into the function from elseware. The parameter list is located between the ( and ) in the function header.


  2. Function Definition
    \begin{lstlisting}[style=cpp] float GetArea( float width, float height ) { return width * height; } \end{lstlisting}

    The function definition is where we actually write what the function does. It includes the same information as the function declaration, but we include the function body in a code block.


  3. Function Body

    The function body is the code block, written between { and }, defining what logic the function performs.


  4. Function Call
    \begin{lstlisting}[style=cpp] float room1Sqft = GetArea( 5, 10 ); float room2Sqft = GetArea( room2width, room2length ); \end{lstlisting}

    After a function is defined, we can then call that function to execute its internal code. If the function has input parameters, we can pass in literal values (hard-coded data) or variables to provide that input data.


  5. Calling a function

    Once the function has been defined, you can call it from anywhere in your program…

    \begin{lstlisting}[style=cpp] int main() { float width, height; cout << "Enter width and height: "; cin >> width >> height; // Call GetArea float area = GetArea( width, height ); cout << "Area: " << area << endl; } \end{lstlisting}


    1. Function Call:

      Calling a function requires the function name, and passing in a series of inputs that become the function's parameters. In the example above, the GetArea function is called, with the values from the width and height variables being passed in. Once GetArea returns its output, that output is then stored in the area variable.


    2. Arguments:

      An argument is the name of the value or variables being passed into the function during the function call. These arguments become the values that the function parameters within the function definition uses.


      Here in the function call, 10 and 20 are the arguments:

      \begin{lstlisting}[style=cpp] // Call GetArea float area = GetArea( 10, 20 ); \end{lstlisting}


      So the values of 10 and 20 get used as the width and length parameters' values:

      \begin{lstlisting}[style=cpp] float GetArea( float width, float height ) { return width * height; } \end{lstlisting}


      The arguments of a function call can be hard-coded values, like 10 and 20 above, or you can pass in other variables as arguments. Then, whatever is stored in those variables is copied over to the parameters.

      \begin{lstlisting}[style=cpp] // Call GetArea twice float area1 = GetArea( room1Width, room1Length ); float area2 = GetArea( room2Width, room2Length ); \end{lstlisting}


      The arguments passed in do not need to share a name with the parameters; these are not the same variables. They're only sharing the data stored within them.

      The first time GetArea is called, whatever is stored within room1Width is copied from that variable and stored in the parameter variable width within the function's definition.


      Common function errors:

      When you're declaring/defining a function you specify data types - the return type and the parameters' data types. When you're calling a function, you do not include data types!

      • YES:

      sqft = GetArea( room_width, room_length );

      • NO:

      sqft = GetArea( float room_width, float room_length );


      Functions must have parentheses ()! If you're missing the parentheses, your program isn't going to call the function!

      • YES:


      • NO:



      If a function contains a return statement, then you must store the returned data in a variable! If you don't assign the return anywhere, it will be lost!

      • YES:

      sqft = GetArea( room_width, room_length );

      • NO:

      GetArea( room_width, room_length );


4.4.4. Variable scope

Scope refers to the location in the code where a variable exists.



If you declare a variable at the top of the main() function, not inside any if statements or loops, then that variable is in scope for the entire duration of main(), starting with the line it was declared on.

\begin{lstlisting}[style=cpp] int main() { int a; // ...etc... } \end{lstlisting}


Variables declared within if statements and loops:

Variables declared within the code block of an if statement or a loop only exists within that code block.

\begin{lstlisting}[style=cpp] if ( a == 3 ) { int b; // only exists within this block } for ( int i = 0; i < 10; i++ ) { cout << i; // only exists within this block } \end{lstlisting}

If you try to use these variables somewhere below the code block, your compiler will give an error, stating that the variable does not exist in that scope. Once the program leaves the code block, the variable is out of scope.



Remember that main() is a function, just like any other functions we write in our program. Any variables declared within a function are local to that function, and accessible anywhere from the variable's declaration until the end of the function.

\begin{lstlisting}[style=cpp] int GetChoice() { int choice; // local variable cout << "Choice: "; cin >> choice; return choice; } \end{lstlisting}



Variables declared in the parameter list of a function are also local to that function and can be used anywhere within the function.

\begin{lstlisting}[style=cpp] int Sum( int a, int b, int c ) { // a, b, and c are local to this function. return a + b + c; } \end{lstlisting}



Same names?

The same name can be reused for different variables in different scopes. Even if they share the same name, they are not related in any way.

\begin{lstlisting}[style=cpp] int GetChoice() { int choice; // Variable A cout << "Choice: "; cin >> choice; return choice; } int main() { int choice; // Variable B choice = GetChoice(); } \end{lstlisting}


4.4.5. Parameters and arguments

  1. Pass-by-value

    When we have a function declared with a parameter…

    \begin{lstlisting}[style=cpp] void Example( int someNumber ) { cout << someNumber; } \end{lstlisting}

    …and we call that function elseware, passing in another variable as an argument…

    \begin{lstlisting}[style=cpp] int main() { int myNumber = 2; Example( myNumber ); return 0; } \end{lstlisting}

    … What happens is that the value of the variable myNumber is copied and passed to the function parameter someNumber. This works the same as if you simply pass in Example( 10 ), passing in a hard-coded value instead of using a variable.


    If you wrote the function to change the value of its parameter, that change would only be reflected within the function and would not affect the original argument passed as part of the function call.

    \begin{lstlisting}[style=cpp] void Example( int someNumber ) { cout << "Example begin: " << someNumber << endl; someNumber = 100; cout << "Example end: " << someNumber << endl; } int main() { int myNumber = 2; Example( myNumber ); cout << "main end: " << myNumber << endl; return 0; } \end{lstlisting}

    The output of this program would be:

    \begin{lstlisting}[style=terminal] Example begin: 2 Example end: 100 main end: 2 \end{lstlisting}

    Even though the value of someNumber from the Example function changes (which is valid), that change doesn't affect myNumber within main(), because only the value was copied over.

    This is known as pass-by-value.


  2. Pass-by-reference

    If we wanted to change the value of an argument variable within a function, we'd have to change the parameter to pass-by-reference. To do this, we use the symbol = &= in the parameter's declaration, after the data type and before the variable name.

    \begin{lstlisting}[style=cpp] void Example( int& someNumber ) { cout << "Example begin: " << someNumber << endl; someNumber = 100; cout << "Example end: " << someNumber << endl; } \end{lstlisting}

    The ampersand symbol can go next to the data type (int & blah), next to the variable name (int &blah), or separate from both (int & blah).

    Once we've made the parameter a reference, then when the function is called, the argument is not copied - a reference to that variable is passed to the function. Any changes to the reference parameter in the function also affects the original argument variable.

    \begin{lstlisting}[style=cpp] int main() { int myNumber = 2; // Calling it looks the same as before Example( myNumber ); cout << "main end: " << myNumber << endl; return 0; } \end{lstlisting}

    The output of this program would be:

    \begin{lstlisting}[style=terminal] Example begin: 2 Example end: 100 main end: 100 \end{lstlisting}


    Pass-by-reference instead of return

    In some cases, you may need to return multiple pieces of data from a function - however, you can only return one item from a function with the return statement (in C++). One option is to set the information you want "returned" as pass-by-reference parameters of the function.

    \begin{lstlisting}[style=cpp] void DoubleTheseNumbers( int & a, int & b, int & c ) { a *= 2; b *= 2; c *= 2; } \end{lstlisting}


    Pass-by-reference of large things

    We haven't gone over arrays or classes/objects yet, but another reason we might want to pass something by-reference instead of by-value is when the parameter is big (which can be the case with arrays and objects).

    If we have a large object we need to pass to a function, doing a copy of the entire thing is inefficient - it is much simpler and faster to pass the large object by-reference.



4.4.6. Summary: Ways to pass data to/from functions

The following table illustrates different ways we can define our parameters, and what the goal is. "RT" means "Return Type", "T" is the "Type" of the parameter.

  Function Read Return Info
1. RT func( T X ) yes no Pass-by-value X
2. RT func( const T& X ) yes no Const pass-by-reference X
3. RT func( T& X ) yes yes Pass-by-reference X
  1. X is pass-by-value, which is fine for primitive data types like ints, floats, chars, and bools.
  2. X is passed by const-reference because X is a mose sophisticated data type like a string or other class-based object. (Longer time to copy if passed by value.)
  3. The function can read from X but also overwrite its value and the change will be reflected back to the argument being passed to the function call.


4.4.7. Default parameters

When declaring a function, you can also set default parameters. These are the default values assigned to the parameters if the user doesn't pass anything in. The default parameters are only specified in a function declaration - NOT the definition!


In this example, it could be a function that displays ingredients for a recipe, and by default the batch is set to 1.0 (one batch).

\begin{lstlisting}[style=cpp] void OutputIngredients( float eggs, float sugar, float flour, float batch = 1.0 ); \end{lstlisting}


The function could be called without passing in a batch:

\begin{lstlisting}[style=cpp] cout << "Ingredients:" << endl; OutputIngredients( 1, 2.0, 3.5 ); \end{lstlisting}


Or they could pass a batch amount explicitly:

\begin{lstlisting}[style=cpp] cout << "Ingredients:" << endl; OutputIngredients( 1, 2.0, 3.5, 0.5 ); // half batch \end{lstlisting}


You can have multiple default parameters specified in your function declaration - but all variables with default values must go after any variables without default values.


4.4.8. Function Overloading

In C++, you can also write multiple functions that have the same name, but a different parameter list. This is known as function overloading.

Let's say you want to be able to sum numbers, and you make a version for floats and a version for integers:

\begin{lstlisting}[style=cpp] int Sum( int a, int b ) { return a + b; } float Sum( float a, float b ) { return a + b; } \end{lstlisting}


You can write as many versions of the function as you like, so long as the function headers are uniquely identifiable to the compiler, which means:

  • The functions have a different amount of parameters, or
  • The data types of the parameters are different, or
  • The parameters are in a different order (when mixing data types).

These will become much more useful once we cover classes and objects.


4.4.9. Review questions:

  1. Build the function signature given the following specs:
    • The function is named "GetRectArea".
    • The function returns a float.
    • The function takes in a float for the width and a float for the length
  2. Identify each code snippet (function declaration / definition / call):
    • a.

      \begin{lstlisting}[style=cpp] float PercentToDecimal( float percent ) { return percent / 100.0; } \end{lstlisting}
    • b.

      \begin{lstlisting}[style=cpp] float PercentToDecimal( float percent ); \end{lstlisting}
    • c.

      \begin{lstlisting}[style=cpp] float decimal = PercentToDecimal( percent ); \end{lstlisting}
  3. Identify how the following parameters are passed (by value / by reference), given this function declaration:

    \begin{lstlisting}[style=cpp] void SomeFunction( int& a, int b ); \end{lstlisting}
    • a is passed… (by value / by reference)
    • b is passed… (by value / by reference)


4.5. Unit 04: Tech Literacy: Debugging, testing, and researching

4.5.1. Syntax

What is syntax?

syntax, noun - The way in which linguistic elements (such as words) are put together to form constituents (such as phrases or clauses)

From the Merriam-Webster Dictionary.

C++, Java, C#, and other "C-like" languages follow similar syntax rules.


Lines of code:

A code statement ends with a semi-colon. Statements are single commands, like using cout ("console out") to display text to the screen, assigning a value to a variable, and other simple operations.

\begin{lstlisting}[style=cpp] string state; // Variable declaration cout << "Enter state: "; // Display text to screen cin >> state; // Getting input from keyboard cout << state << endl; // Displaying text to the screen \end{lstlisting}



Comments are notes left in the code by humans for humans. They can help us remember what our code was doing later on, or help guide someone else reading through our code. There are two ways we can write comments in C++.

If we use // then all text afterwards will be a comment. This is a single-line comment. If we use /* then all text will be a comment, only ending once we reach a */. This is a multi-line comment.

\begin{lstlisting}[style=cpp] string state; // Variable declaration /* Next we're going to search for this state in the list of all states that match xyz criteria... */ \end{lstlisting}


Code blocks:

There are certain types of instructions that contain additional code. If statements, for example, contain a set of instructions to execute only if the condition given evalutes to true. Any time an instruction contains additional instructions, we use opening and closing curly braces { } to contain this internal code. Note that an if statement and other structures that contain code don't end with a semicolon ;.

\begin{lstlisting}[style=cpp] if ( price > 100 ) { // Code block begin cout << "Too expensive..." << endl; } // Code block end \end{lstlisting}


4.5.2. Types of errors

Syntax errors and logic errors


Syntax errors are errors in the language rules of your program code. This include things like typos, misspellings, or just writing something that isn't valid C++ code, such as forgetting a ; at the end of some instructions. Although they're annoying, syntax errors are probably the "best" type of error because the program won't build while they're present. Your program won't build if you have syntax errors.

Logic errors are errors in the programmer's logic. This could be something like a wrong math formula, a bad condition on an if statement, or other things where the programmer thinks thing A is going to happen, but thing B happens instead. These don't lead to build errors, so the program can still be run, but it may result in the program crashing, or invalid data being generated, or other problems.


Minimizing bugs and debugging time


  • Write a few lines of code and build after every few lines - this will help you detect syntax errors early.
  • DON'T write the "entire program" before ever doing a build or a test - chances are you've written in some syntax errors, and now you'll have a long list of errors to sift through!
  • If you aren't sure where an error is coming from, try commenting out large chunks of your program until it's building again. Then, you can un-comment-out small bits at a time to figure out where the problem is.



4.5.3. Testing software

  1. Why test?


    How do you know that your program actually works?

    Sure, you may have manually tested your code, running the program and typing in test data and checking the output. After a while, manual testing becomes a chore. Maybe you start entering "asdjhfklq" as the test data and just make sure nothing breaks while running the program. But are you sure your program runs, doesn't crash, and gives the correct output for all reasonable cases?

    A skill that is good to develop as a software developer is how to test and validate your work. You can break down parts of your code into little transactions of "inputs" and "outputs", and then develop test cases.

    • Test case: A test case is a single test. You specify some input(s) that you will give your program, and the expected output(s) it should return.

    When you run the actual program with your inputs, it will return actual output(s). Compare the actual output with the expected output to validate whether the program worked as expected. Test cases can be built without any of the program built so far. In fact, it can be handy to write your tests ahead of time so you have a better understanding of how things are supposed to work.


  2. Writing test cases

    Example: Bank withdrawals

    In this example, the program keeps track of a bank balance and the amount the user wants to withdraw, but it shouldn't let the balance fall below 0.

    Test case Input(s) Expected output Actual output
    1 balance = 100, withdraw = 10 balance is now 90  
    2 balance = 0, withdraw = 100 can't withdraw!  
    3 balance = 100, withdraw = 100 balance is now 0  

    You would make a list of inputs and what should be the result for each case, and then run your program and check each scenario - does the actual output match the expected output? If something doesn't match, it could mean that there's an error in a calculation somewhere, or other logic in the program. (And yes, sometimes tests can be wrong, too.)

  3. Ways to test

    Testing is a whole job title in software development. Usually the "developers" write the new features and maybe add unit tests for their code. A dedicated QA (Quality Assurance) or SET (Software Engineer in Test) is then responsible for thoroughly testing developer work. This includes testing in multiple ways, both the feature itself "in a vacuum", and connected to the entire system as a whole, to make sure that nothing breaks along the way.

    1. Manual testing

      Manually testing is as it sounds - the QA has a list of test cases in a document or wiki and they follow those test cases to make sure the program continues working. Often this means navigating the program's UI from the user's perspective, going through each step to make sure nothing breaks.

    2. Integration tests

      Integration tests test the new feature within the entire system as a whole, integrated with the rest of the program. Usually companies will have multiple servers, such as a QA server where the program is set up like it's ready for the real world, but only used by testers and filled with test/mock data. This is usually where integration tests happen - we want to make sure it works before we push to production (in other words, submit the new feature to the live website or app that the actual users are using.)

    3. Unit tests

      Often the developers who write features are required to also write unit tests for those features. Unit tests are a way to test "in a vacuum", one unit at a time. They're handy for making sure that each individual component of a feature doesn't break. Unit tests are automated - you can write something like

      \begin{lstlisting}[style=cpp] // Inputs for this test case int input_balance = 100; int input_withdraw = 10; // What the expected result (balance) is int expected_output = 90; // Call the function that handles it with the // test case inputs, its output is our "actual output". int actual_output = Withdraw( input_balance, expected_output ); if ( actual_output == expected_output ) { // If the actual output matches // the expected output - PASS! cout << "Test passes!" << endl; } else { // The actual output didn't match, so test FAILS. cout << "TEST FAILS!" << endl; } \end{lstlisting}

      Again, for reference, the first test case is written out as:

      Test case Input(s) Expected output
      1 balance = 100, withdraw = 10 balance is now 90


  4. Test driven development

    In the book Test-Driven Development by Kent Beck, he highlights a way of approaching software development where you write your tests for a new feature first, before writing any actual code to implement that feature. By writing tests first, it helps developers think through the actual requirements in a quantifiable way. You can read more about it on the Wikipedia page - https://en.wikipedia.org/wiki/Test-driven_development .

    I think it's an interesting way to approach design and development, though from my experience no company I've ever worked for has used this test-first approach. I do find this a good way to go about designing solutions during job interview questions! (Plus it gives you stalling time as you ask your interviewer questions about the requirements, gives you more time to think through your design, and gives you a way to verify your work afterwards. ;)


4.5.4. Doing research as a programmer

For developers it's a pretty common experience for people to feel like they spend a lot of their time searching for solutions and scouring Stack Overflow posts for solutions to their troubles. In the professional world you will be learning your company's codebase, as well as probably learning third party APIs from other companies as well. While you may be proficient in the language you work in, learning other peoples' code and products will always be part of it. So, research is part of development.


  1. Internal wikis and documentation


    Companies often have some kind of internal Wiki (or Confluence, or Sharepoint) where employees can post documentation and notes to share with others. However, developers don't usually do much documentation on their code or code they've explored, so usually a company's internal documentation for their own code is pretty bad. (In my experience only the auto-generated API docs built from code comments are okay.)


  2. Search engines (and AI?)

    Searching on a search engine can come up with tutorials, blogs, API docs, message board posts, and other resources for reference. Finding help, documentation, examples, and posts where someone else had the same problem is a common way of working through problems, as well as asking coworkers, sketching out the problem on paper, and testing out different approaches.

    As Large Language Models ("AI") becomes more popular, it may be tempting to try to ask it all of your questions. However, there's no intelligence in this LLM-based AI, it's not thinking critically about what you've said, and it can frequently get things wrong but in a confident manner. I would suggest that you use it as a starting point, somewhere to get some ideas, rather than utilizing it as actual documentation.


  3. Documentation resources


    Figure 10: A screenshot of the documentation page for Canvas' API, listing an action, inputs, and other information.

    When working with third party libraries and APIs that are provided by another business or organization they will generally have decent documentation explaining the items you can use. Going over API documentation is a big part of software development. :) So having the patience to read through docs to find what you need is important.

    If you want to see some examples of API documentation, here are a few. You can also search "[thing] API docs" to find documentation for a lot of things, from meal delivery apps to catalogs of venomous frogs in Australia.


  4. Stack Overflow and message boards

    As you do web searches for programming problems (for me, usually build error messages - what does it mean? :)) often you will see message boards with archived posts from people with similar problems. These are pretty common to reference, though can be limited in how helpful they are. Sometimes the poster's problem matches yours, sometimes nobody responded, sometimes you can't quite find what you need. But still a common resource.


  5. Language reference resources


    Figure 11: An image of the cover of the book "JavaScript Pocket Reference", published by O'Reilly.

    It's good to keep a reference book about the language you're using as well. These can usually be college style textbooks about the language, or maybe a quick reference. There are also books that help you gain a deeper understanding of the language, frameworks, and tools you use.

    There are also often online video lessons that can teach you about technologies as well. These are usually through websites like Pluralsight or maybe Coursera or Udemy.

    The software/web/mobile development landscape is always changing so as a developer you will often need to keep up with updates that your company makes to frameworks and technologies.



4.6. Unit 05: C++: Structs

4.6.1. Introduction to objects


Programming paradigms (pronounced "pair-uh-dimes") are ways we can classify different programming styles. Some programming languages support multiple paradigm styles and some are restricted to one style of coding. Over the decades different paradigms have been developed and evolved over time. Object Oriented Programming is one of the most common styles of programming these days, and is a big part of how C++, C#, and Java-based programs are designed.


  1. What are "Objects"?

    Defining classes and structs in our programs are a way that we can create our own data types for our variables. When we define our own structures, we can create them with internal variables and functions available to them. The variables we create, whose data types come from a defined class or struct, is known as an object.

    Design-wise, the idea is to take real-world objects and find a way to represent them in a computer program as an object that has attributes (variables) and functionality (functions).


  2. OOP design ideals

    The concept of Object Oriented Programming is creating a design that is easy to maintain over time. In particular, there are some core design goals behind OOP, including:

    • Encapsulation: Giving the user / other programmers an “interface” \ to interact with the objects, hiding the inner-workings within the class.
      • Certain functions are made public, which other programmers can use to interface with the object.
      • The other programmers don't need to worry about the inner-workings of the object in order to use it.
      • The developer of the class can modify how the internals work without breaking the public interface.
      • Helps protect the data within the class from being accessed or modified by external things that shouldn't have access to it.
    • Loose coupling: Ideally, different objects in a program shouldn't have their functionality tied to other objects too closely; we wan tto reduce inter-dependence between objects. When objects are more independent from each other, we say they are loosely coupled.
    • High cohesion: When we design our objects, we shouldn't just throw everything and the kitchen sink into one object. To design an object with high cohesion means that everything inside the object belongs to that object - reduce the clutter.


4.6.2. Separate variables to one struct

Structs are a way we can group related information together into one data type.

For example, let's say we were writing a program for a restaurant, and an item on the menu would have a name, a price, a calorie count, and a "is it vegetarian?" signifier. We could declare these all as separate variables:

\begin{lstlisting}[style=cpp] string food1_name; float food1_price; int food1_calories; bool food1_is_veggie; \end{lstlisting}


But there isn't really anything in the program that says these variables are related, except that we as humans have given these variables similar prefixes in their names. A better design would be to create a new datatype called MenuItem (or something similar), and the MenuItem will contain these four variables within it. We're basically making a variable data type that can contain multiple variables!


First we create the struct, which should go in its own .h file:


\begin{lstlisting}[style=cpp] struct MenuItem { string name; float price; int calories; bool isVeggie; }; \end{lstlisting}


And then we can declare variables of this type in our program:


\begin{lstlisting}[style=cpp] MenuItem food1; food1.name = "Bean Burrito"; food1.price = 1.99; food1.calories = 350; food1.isVeggie = true; MenuItem food2; food2.name = "Crunchy Taco"; food2.price = 1.99; food2.calories = 170; food2.isVeggie = false; \end{lstlisting}


4.6.3. Multiple files in C++ programs


When creating a struct, we should create a new source code file in our project. Usually the name of the file will be the same name as the struct, with a .h at the end. This is a header file and declarations for structs (and functions and classes later) will go in these types of files.


Something you need to require in your .h files that isn't needed for your .cpp files are file guards. These prevent the compiler from reading the file more than once. If it reads it multiple times, it will think you're redeclaring things over and over again. Your .h files should always look like this:

\begin{lstlisting}[style=cpp] #ifndef _MYFILE_H #define _MYFILE_H // put code here #endif \end{lstlisting}

Where the "_MYFILE_H" should be changed to something unique in each file - usually, the name of your file.


4.6.4. Creating our own structs

A basic struct declaration is of the form…

\begin{lstlisting}[style=cpp] #ifndef _MYFILE_H #define _MYFILE_H struct STRUCTNAME { // member variables int MEMBER1; string MEMBER2; float MEMBER3; }; #endif \end{lstlisting}

Note that the closing curly-brace } must end with a ; otherwise the compiler will give you errors.

You can name your struct anything you'd please but it has to abide by the C++ naming rules (no spaces, no keywords, can contain letters, numbers, and underscores).

Any variables we declare within the struct are known as member variables - they are members of that struct.

Any new variables you declare whose data type is this struct will have its own copy of each of these variables.


  1. Declaring object variables

    A object is a type of variable whose data type is a struct (or class). To declare a variable whose data type is a struct, it looks like any normal variable declaration:

    \begin{lstlisting}[style=cpp] DATATYPE VARIABLE; \end{lstlisting}


  2. Accessing member variables

    Our struct object variables each have their own member variables, which we access via the dot operator .. We can assign values to it, our read its value, similar to any normal variable.

    \begin{lstlisting}[style=cpp] VARIABLE.MEMBER1 = 10; VARIABLE.MEMBER2 = "ASDF"; VARIABLE.MEMBER3 = 2.99; cout << VARIABLE.MEMBER1 << endl; \end{lstlisting}


  3. Example: Fraction struct

    First we would declare our Fraction struct within Fraction.h:

    \begin{lstlisting}[style=cpp] #ifndef _FRACTION_H #define _FRACTION_H struct Fraction { int num; int denom; }; #endif \end{lstlisting}

    Within main(), we could then create Fraction variables and work with them:


    \begin{lstlisting}[style=cpp] #include "Fraction.h" int main() { Fraction frac1, frac2, frac3; cout << "FIRST FRACTION" << endl; cout << "* Enter numerator: "; cin >> frac1.num; cout << "* Enter denominator: "; cin >> frac1.denom; cout << endl; cout << "SECOND FRACTION" << endl; cout << "* Enter numerator: "; cin >> frac2.num; cout << "* Enter denominator: "; cin >> frac2.denom; frac3.num = frac1.num * frac2.num; frac3.denom = frac1.denom * frac2.denom; cout << endl; cout << "PRODUCT: " << frac3.num << "/" << frac3.denom << endl; return 0; } \end{lstlisting}


4.6.5. Review questions:

  1. File guards are needed because…
  2. What kind of data would be good to represent with a struct?
    • A character in a video game including the amount of experience points they have, their current hit points, and current level
    • The tax rate of a city
    • The URL of a website you're visiting
    • An address, including recipient name, street address, city, state, and zip code
  3. If we declared an object variable like Course cs200; , How would we assign "cs" to the department member variable and 200 to the code member variable?


4.7. Unit 06: Tech Literacy: Careers in tech

Here I tried to summarize, or find text summaries of, descriptions of different common roles in tech. I myself have worked as a Software Engineer and have worked on teams with QAs, Software Engineers in Test, Business Analysts, UI/UX Designers, and Database Admins, but most of my first-hand experience is the development side of things.

If you're interested in some particular fields, I have added links to YouTube videos from various people that describe more about the roles. In the PDF file you should be able to click the links to access them on the web.


4.7.1. Roles in Tech

  1. Software Engineer

    The software engineering role is probably what most people think of when they're thinking of software development. They are the people who implement the features that we use on apps, webpages, and software. This may include working on the front end code (the user interface code/markup), back end code (how the processing gets done on the server-side or behind-the-scenes), database scripts (accessing, updating, and writing data).

    Usually a development team will have at least 2 - 3 software engineers who split the list of tasks to be implemented in the code base, and they work closely with the UI/UX design, Software Engineers in Test, and the product managers who decide what is going to get implemented.


  2. Software Engineer in Test

    A software engineer in test role is another type of programming role but the developer focuses on the testing of features and the code base, rather than development new features. This can include writing automated tests to check the program's back-end functionality, automated scripts to test usability from the GUI side, and even doing manual testing in the program and with additional tools. It's their job to look for any oversights the developers may have made while implementing their new feature, and making sure the new features don't break any existing functionality.

    Average teams may have one or two software engineers in test on a team.


  3. Quality Assurance

    Colloquially, a person in a Quality Assurance test role with software development doesn't do as much coding as a Software Engineer in Test. They may write basic scripts but sometimes their background isn't even in coding. A lot of this includes manually testing the software (usually from the GUI) and documenting the steps on how to test a given feature.

    Teams may have both QA testers and software engineers in test, or one, or the other. It kind of depends on the application itself!


  4. Database Admin

    Software and websites need to store data, whether it's all the products available in a store, or a series of chat messages between users. The database is its own area that needs specialized people to build and maintain, even if software developers occasionally write their own tables and scripts. Databases also require maintenance of the actual servers where the database lives, as well as configuration, migration, and more.


  5. UX Design

    The User Experience Designer is more about the entire experience of using the product. In a way, think of a person who figures out what kind of features might be important to a user - is "clicking once to purchase an item online" a feature that users would desire? UX is somewhat more about functionality, and they work with UI and developers to figure out how to create the solution.


  6. UI Design

    UI Designer is more of a visual, graphical role, creating a pleasant interface for customers/users who are using the product. It is important to be able to present information clearly, and to be consistent across the entire product. Depending on the company, sometimes the UI designer may also write HTML and CSS, but not always. Still, learning some basic coding with HTML, CSS, and JavaScript can be a huge asset as a designer.


  7. DevOps

    DevOps engineers reduce that complexity, closing the gap between actions needed to quickly change an application, and the tasks that maintain its reliability.

    DevOps is all about the unification and automation of processes, and DevOps engineers are instrumental in combining code, application maintenance, and application management. All of these tasks rely on understanding not only development life cycles, but DevOps culture, and its philosophy, practices, and tools.


  8. Business Analyst

    Business analysts (BAs) are responsible for bridging the gap between IT and the business using data analytics to assess processes, determine requirements and deliver data-driven recommendations and reports to executives and stakeholders.

    BAs engage with business leaders and users to understand how data-driven changes to process, products, services, software and hardware can improve efficiencies and add value. They must articulate those ideas but also balance them against what’s technologically feasible and financially and functionally reasonable.

    (Description from



  9. IT Specialist

    IT is needed anywhere a company has computers. This can include places that develop software, but also companies that don't develop software and still need someone to set up and maintain the office's systems. This may include the actual computer systems, the network and wifi, maintaining in-building server(s), and otherwise providing tech support for the employees of the company. Coding in IT can include writing scripts (e.g., UNIX scripts) to automate configuring many systems, or writing utilities to help you diagnose issues or otherwise do your job.


  10. Product Manager

    A product manager is the person who identifies the customer need and the larger business objectives that a product or feature will fulfill, articulates what success looks like for a product, and rallies a team to turn that vision into a reality.

    (Description from



  11. Information Security

    People working in InfoSec or CyberSecurity helps protect a company's assets from bad actors. This can mean anything from teaching a company's employees about scams and phishing attempts, monitoring network traffic to the application/website and looking for people trying to gain unauthorized access or sending bad data, and otherwise evaluate threats.


  12. Data Scientist, Data Analyst, Data Engineer

    Tons of data is passed around everyday, from the way a product is used to customer data. Many companies collect this data but with so many data points, what do you even do with it? Working in Data Science is about interpreting and presenting the data, or training machines to learn patterns to predict how the software will be used, or how different pieces of data are related.

    (Description from



4.7.2. Professional development and networking

One of the easiest ways to get your foot in the door at a company is by knowing somebody who is already working there. This could be somebody that you went to school with, somebody that you’ve worked with previously, or even someone you’ve met through conferences or via the internet. But, how do you go about making contacts and keeping in touch? You can build your network of professionals in various ways throughout the years. Here are some of the ways that I've met other developers throughout my career…


One of the easiest ways to meet people right now is meeting your classmates. For some of us, our style might be “go to class, do the work by myself, don’t talk to others” (like me, I was a shy youngin’), but making contacts at school can go a long way.

While in school, being able to discuss assignments, work on homework together, and give each other tips and tricks for programming can be helpful, and outside of school you can keep in touch and keep tabs on where each other is working, share information on good companies to work for and bad, compare salaries to make sure you’re getting compensated fairly, etc.

School clubs can be a good way to meet others, both inside and outside your area of study. You can view a list of JCCC clubs and organizations here:


The school may also have events from time-to-time to get you and your work exposed to local businesses and professionals, such as regular career fairs and poster symposiums. You may need to keep an eye on campus news for these! The CSIT department hosts a reverse career fair once a year so keep an eye out!

As you have jobs (whether they’re software development or not), try to make sure to keep in touch with one or more coworker. With coworkers especially, they will be able to better vouch for you and how you work if you end up applying for a job with them at a different company as well.
Your friends have their own professional networks and, even if they're not in tech, they might know others who are, or know of other companies that hire tech people.
Conferences and meetups:

You can also connect with other professionals at events and conferences. It could be tech conferences or events for other topics (you don’t exclusively need to keep in touch with just software developers; knowing non-developers can also be helpful in finding opportunities!).

I know during the pandemic it can be difficult to do this kind of in-person networking. Some events have moved to online, and some have just canceled. If you attend an in-person event or a virtual event, you could try to connect with people you meet or whose talks you listen to via LinkedIn or Twitter (a lot of people who talk at conferences will have a Twitter).

Some local conferences:
  • KCDC – Kansas City Developer Conference


    Yearly conferences that feature developers from Kansas City and elseware giving talks about various technology, practices, and more. This can be a good place to learn the basics of a new area and meet with others. They also have a booth area where you can talk to recruiters and developers from different companies.

  • MINK WIC – Missouri/Iowa/Nebraska/Kansas Women in Computing


    This is a conference for women in tech in the surrounding area. Each year the conference is held in a different one of the four states and also includes talks and presentations and company booths.

Some local groups
  • Flyover Indies - Gamedev Meetup


    Flyover Indies is a group of independent game developers here in the KC Metro area. There's a co-working afternoon on Sundays, a Ludology club studying about game development concepts, and more.

  • SecKC – Security Meetup


    SecKC is a meetup of people interested in the security side of tech. They usually meet monthly.

Other ideas
  • Meetup.com - You can find other meetups for specific areas (e.g., just Python, just web development, etc.) on Meetup.com. Going to meetings will help you become acquainted with other developers and learn about businesses locally, as well as give you a chance to ask questions and get advice.
  • Other conferences - Try searching online for conferences related to your area of interest in other parts of the country or world! They might have deals on tickets for students, or have some online component.
  • Online communities - Sometimes you can find Slack or Discord servers for people in a specific field (e.g., ".net developers", "women in tech", etc.) and it can be handy to be a part of these groups.
  • Reddit - Some students have suggested that you can network with others via Reddit as well.
  • Discord and IRC chat - Find a group of hobbyists, open source developers, or other areas and join the community! Even libraries like SFML have their own community.


4.7.3. What about AI?

You don't have to read this if you don't want to, I'm just rambling here.


All the big tech companies seem to be buying into adding AI into their products these days, but I see this as repeated history, such as the frenzy about NFTs in the past five years, or the dot com bubble of the late 1990s.


Basically, companies make money if their investors are excited about something. We already saw how many companies announced some kind of "blockchain" or "NFT" based feature they were going to create, which seems to have somewhat quietly died down in the past year or two. Companies throw something out there, whether it's an idea they are actually excited about or not, just to get an influx of cash from investors.


Just like with NFTs and AI, in the 1990s any business touting having a website would get funding, even if the business idea was not viable. Investors were excited about the potential to make a ton of money off the hot new technology: the Internet.


Here in 2024, the pumping up of AI technologies seems to be the exact same thing. From a standpoint of how LLMs work, the layperson seems to have an idea of what "Artificial Intelligence" is from decades of movies and media presenting it in a certain way, and I think investors tend to be non-technical people who buy into this idea as well. Tech companies are telling us all they're integrating AI into their products so that they get more money from investors and generate more buzz to stay relevant.


But in my mind there is a disconnect: We could use Large Language Models and "AI" in very useful, helpful ways. We could train these technologies in an ethical manner and it could help us with real tasks, but that's not what is even happening here. These companies have basically trained their models indescriminately on tons of information from random places of the internet, no specializations and no quality control measures. A Large Language Model is basically good at predicting which word comes next in a sentence, based on the patterns it has seen in its training data.


If AI is a danger to your potential future jobs as a software developer, I do not believe that it is because AI will replace you as a programmer. I think that the reasons for the current garbage job market is more complex, such as:

  • Non-technical bosses and investors think they can save money by using AI instead of developers, but doing so will create erroneous, flawed products. (Will they be humble enough to backtrack on their decisions in order to fix it? Doubtful.)
  • More companies than usual may be using "AI" to try to pair down a pool of applications, even though this bakes in historical bias into what resumes are brought forward - or the ability to game the system if a candidate knows how to appeal to the algorithm.
  • Companies currently like to inflate their profit margins by laying off employees before the end of a quarter. This is also contributing to lack of jobs.
  • At the same time, it looks good for companies to be "searching for jobs" by posting jobs online, even without the intention of hiring for those jobs.

There's a lot more to ramble about when it comes to AI (e.g., companies don't want employees pasting company code into LLMs because company secrets, how do you train to be a prompt engineer if we have no control over how these companies/organizations change their AI models, is it ethical for an AI to scrap webpages and return a summary of answers rather than sending searchers to webpages, is it ethical to train AI on art, code, and articles that are publically available but without the authors' consent, and lots more things), but I'll leave it at that for now.

(Written May 2024)


4.8. Unit 07: C++: Looping

4.8.1. Boolean expressions

In order to start writing questions that a computer can understand, we need to understand boolean expressions.


A math expression looks like this:

\[ 2 + 3 \]

A boolean expression is a statement that result in either true or false:

"it is daytime."

"the user saved the document"

"the user's age is greater than 12 and less than 20"


if ( i_have_not_been_fed && it_is_6_am ) {


Logic in computer programs are based around these types of questions: something that can only be true or false. Statements include:

  • Is [boolean variable] true?
\begin{lstlisting}[style=cpp] x \end{lstlisting}
  • Is [boolean variable] false?
\begin{lstlisting}[style=cpp] !x \end{lstlisting}
  • Are two variables equal?
\begin{lstlisting}[style=cpp] x == y \end{lstlisting}
  • Are two variables not equal?
\begin{lstlisting}[style=cpp] x != y \end{lstlisting}
  • Is x less than y?
\begin{lstlisting}[style=cpp] x < y \end{lstlisting}
  • Is x less than or equal to y?
\begin{lstlisting}[style=cpp] x <= y \end{lstlisting}
  • Is x greater than y?
\begin{lstlisting}[style=cpp] x > y \end{lstlisting}
  • Is x greater than or equal to y?
\begin{lstlisting}[style=cpp] x >= y \end{lstlisting}


For the first two, we can check the value of a boolean variable. The rest of them, we can use any data type to compare if two values are equal, greater than, less than, etc. a and b can be replaced with variables and/or values…

\begin{lstlisting}[style=cpp] if ( age < 18 ) { ... } if ( my_state == your_state ) { ... } if ( word1 < word2 ) { ... } if ( document_saved == true ) { ... } if ( document_saved == false ) { ... } \end{lstlisting}

Note: When using \(<\) and \(>\) with strings or chars, it will compare them based on alphabetical order - if they're both the same case (both uppercase or both lowercase). The code 65 represents 'A', but the code 97 represents 'a', so items will be "sorted" based on these codes.


  1. And, Or, and Not operators

    We can also combine boolean expressions together to ask more sophisticated questions.

    1. Not operator: !

      If we're checking a boolean variable, or a boolean expression, and we happen to want to execute some code for when that result is false, we can use the not operator…

      Using with boolean variable documentSaved:

      \begin{lstlisting}[style=cpp] // Just checking documentSaved is true if ( documentSaved ) { Quit(); } // Checking if documentSaved is false if ( !documentSaved ) { Save(); Quit(); } \end{lstlisting}

      Using with boolean expressions ( age >= 21 ):

      \begin{lstlisting}[style=cpp] // If the age is not 21 or over... if ( !( age >= 21 ) ) { NoBeer(); } \end{lstlisting}


    2. And operator: &&

      When using the and operator, we can check to see if all boolean variables/expressions are true. The full question of "is this and this and this true?" only results to true if all boolean variables/expressions are true. If even one of them are false, then the entire statement is false.

      \begin{lstlisting}[style=cpp] if ( wantsBeer && isAtLeast21 ) { GiveBeer(); } \end{lstlisting}

      To break it down, the customer would only get beer if they want beer AND if they are over 21. If they don't want beer but are 21 or over, they don't get beer. If they want beer but are under 21, then they don't get beer.


    3. Or operator: ||

      For an or operator, we can check to see if at least one boolean variable/expression is true. If at least one item is true, then the whole statement is true. The only way for it to be false is when each boolean variable/expression is false.

      \begin{lstlisting}[style=cpp] if ( isBaby || isSenior || isVet ) { GiveDiscount(); } \end{lstlisting}

      In this case, discounts are given to babies, seniors, and vets. A customer wouldn't have to be all three to qualify (and clearly, couldn't be all three at the same time!). If the customer is not a baby and not a senior and not a vet, then they don't get the discount - all three criteria have to be false for the entire expression to be false.


  2. Truth tables

    We can use truth tables to help us visualize the logic that we're working with, and to validate if our assumptions are true. Truth tables are for when we have an expression with more than one variable (usually) and want to see the result of using ANDs, ORs, and NOTs to combine them.


    1. Truth table for NOT:

      On the top-left of the truth table we will have the boolean variables or expressions written out, and we will write down all its possible states. With just one variable \(p\), we will only have two states: when it's true, or when it's false.

      On the right-hand side (I put after the double lines) will be the result of the expression - in this case, "not-p" \(!p\). The not operation simply takes the value and flips it to the opposite: true \(\to\) false, and false \(\to\) true.

      p !p
      T F
      F T


    2. Truth table for AND:

      For a truth table that deals with two variables, \(p\) and \(q\), the total amount of states will be 4:

      1. \(p\) is true and \(q\) is true.
      2. \(p\) is true and \(q\) is false.
      3. \(p\) is false and \(q\) is true.
      4. \(p\) is false and \(q\) is false.
      p q   p && q
      T T   T
      T F   F
      F T   F
      F F   F

      This is just a generic truth table. We can replace the values with boolean expressions in C++ to check our logic.


    3. Truth table for OR:

      This also deals with 2 variables, \(p\) and \(q\), so 4 total states. If at least one of the two variables are true, then the entire expression is true. An expression with an "or" is only false when all sub-expressions are false.

      p q p ‖ q
      T T T
      T F T
      F T T
      F F F


    4. Example - AND:

      We will only quit the program if the game is saved and the user wants to quit:

      game_saved want_to_quit game_saved && want_to_quit
      T T T
      T F F
      F T F
      F F F

      The states are:

      1. T: gameSaved is true and wantToQuit is true: Quit the game.
      2. F: gameSaved is true and wantToQuit is false: The user doesn't want to quit; don't quit.
      3. F: gameSaved is false and wantToQuit is true: The user wants to quit but we haven't saved yet; don't quit.
      4. F: gameSaved is false and wantToQuit is false: The user doesn't want to quit and the game hasn't been saved; don't quit.


    5. Example - OR:

      If the store has cakes OR ice cream, then suggest it to the user that wants dessert.

      hasCake hasIcecream hasCakehasIceCream
      T T T
      T F T
      F T T
      F F F

      The states are:

      1. T: hasCake is true and hasIcecream is true: The store has desserts; suggest it to the user.
      2. T: hasCake is true and hasIcecream is false: The store has cake but no ice cream; suggest it to the user.
      3. T: hasCake is false and hasIcecream is true: The store has no cake but it has ice cream; suggest it to the user.
      4. F: hasCake is false and hasIcecream is false: The store doesn't have cake and it doesn't have ice cream; don't suggest it to the user.


  3. DeMorgan's Laws

    Finally, we need to cover DeMorgan's Laws, which tell us what the opposite of an expression means.

    For example, if we ask the program "is a \(>\) 20?" and the result is false, then what does this imply? If \(a > 20\) is false, then \(a \leq 20\) is true… notice that the opposite of "greater than" is "less than OR equal to"!


    1. Opposite of a && b
      a b a && b !( a && b ) !a ‖ !b
      T T T F F
      T F F T T
      F T F T T
      F F F T T

      If we're asking "is \(a\) true and is \(b\) true?" together, and the result is false, that means either:

      1. \(a\) is false and \(b\) is true, or
      2. \(a\) is true and \(b\) is false, or
      3. \(a\) is false and \(b\) is false.


      These are the states where the result of a && b is false in the truth table.


      In other words,

      !( a && b ) \(\equiv\) !a ‖ !b

      If \(a\) is false, or \(b\) is false, or both are false, then the result of a && b is false.


    2. Opposite of a ‖ b:
      a b a ‖ b !( a ‖ b ) !a && !b
      T T T F F
      T F T F F
      F T T F F
      F F F T T

      If we're asking "is \(a\) true or \(b\) true?", if the result of that is false that means only one thing:

      1. Both \(a\) and \(b\) were false.

      This is the only state where the result of a || b is false.


      In other words,

      !( a ‖ b ) \(\equiv\) !a && !b

      a ‖ b is false only if \(a\) is false AND \(b\) is false.


    3. Summary

      In order to be able to write if statements or while loops, you need to understand how these boolean expressions work. If you're not familiar with these concepts, they can lead to you writing logic errors in your programs, leading to behavior that you didn't want.



4.8.2. While loops

While loops look a lot like if statements…

\begin{lstlisting}[style=cpp] while ( CONDITION ) { // Do stuff repeatedly } \end{lstlisting}

except that they will continue looping while their condition is true. Once the condition results in false, then the loop will stop and the program will continue after the while loop's code block.


Because a while loop will keep going until the condition is false, it is possible to write a program where the condition never becomes false, resulting in an infinite loop!

The while loop's condition is another boolean expression - a statement that will be true or false.


  1. Example: Counting up

    The following while loop will increase a variable by 1 each time and display it to the screen.

    \begin{lstlisting}[style=cpp] int num = 1; while ( num < 10 ) { cout << num << "\t"; num++; // add 1 to num } \end{lstlisting}


    \begin{lstlisting}[style=terminal] 1 2 3 4 5 6 7 8 9 \end{lstlisting}


  2. Example: Program loop

    In some cases, you'll have a main menu and want to return the user back to that menu after each operation until they choose to quit. You could implement this with a basic boolean variable:

    \begin{lstlisting}[style=cpp] bool done = false; while ( !done ) { cout << "Option: "; cin >> option; if ( option == "QUIT" ) { done = true; } } cout << "Bye" << endl; \end{lstlisting}


  3. Example: Validating user input

    Sometimes you want to make sure what the user entered is valid before continuing on. If you just used an if statement, it would only check the user's input once, allowing them to enter something invalid the second time. Use a while loop to make sure that the program doesn't move on until it has valid data.

    \begin{lstlisting}[style=cpp] cout << "Enter a number between 1 and 10: "; cin >> num; while ( num < 1 || num > 10 ) // out of bounds! { cout << "Invalid number! Try again: "; cin >> num; } cout << "Thank you" << endl; \end{lstlisting}


    \begin{lstlisting}[style=terminal] Enter a number between 1 and 10: 100 Invalid number! Try again: -400 Invalid number! Try again: -5 Invalid number! Try again: 5 Thank you \end{lstlisting}


  • Do… while loops

    A do…while loop is just like a while loop, except the condition goes at the end of the code block, and the code within the code block is always executed at least one time.

    \begin{lstlisting}[style=cpp] do { // Do this at least once } while ( CONDITION ); \end{lstlisting}


    For example, you might want to always get user input, but if they enter something invalid you'll repeat that step until they enter something valid.

    \begin{lstlisting}[style=cpp] do { cout << "Enter a choice: "; cin >> choice; } while ( choice > 0 ); \end{lstlisting}


  • Special commands
    1. continue

      Sometimes you might want to stop the current iteration of the loop, but you don't want to leave the entire loop. In this case, you can use continue; to skip the rest of the current iteration and move on to the next.

      \begin{lstlisting}[style=cpp] int counter = 10; while ( counter > 0 ) { counter--; if ( counter % 2 == 0 ) // is an even number? { continue; // skip the rest } cout << counter << " odd number" << endl; } \end{lstlisting}


      \begin{lstlisting}[style=terminal] 9 odd number 7 odd number 5 odd number 3 odd number 1 odd number \end{lstlisting}


    2. break

      In other cases, maybe you want to leave a loop before its condition has become false. You can use a break; statement to force a loop to quit.

      \begin{lstlisting}[style=cpp] while ( true ) // Infinite loop :o { cout << "Enter QUIT to quit: "; cin >> userInput; if ( userInput == "QUIT" ) { break; // stop looping } } \end{lstlisting}


  • Review questions:
    1. A while loop will continue looping while its condition is…
    2. What does the continue command do?
    3. What does the break command do?


  • 4.8.3. For loops

    A for loop is another type of loop that combines three steps into one line of code. A for loop looks like this:

    \begin{lstlisting}[style=cpp] for ( INIT_CODE ; CONDITION ; UPDATE_ACTION ) { } \end{lstlisting}
    • INIT CODE: This is some code that is executed before the loop starts. This is usually where a counter variable is declared.
    • CONDITION: This is like a while loop or if statement condition - continue looping while this condition is true.
    • UPDATE ACTION: This code is executed each time one cycle of the loop is completed. Usually this code adds 1 to the counter variable.

    Technically you can use the for loop in a lot of ways, but the most common use is something like this:

    \begin{lstlisting}[style=cpp] for ( int i = 0; i < 10; i++ ) { // Do something 10 times cout << i << "\t"; } \end{lstlisting}

    For loops are especially useful for anything that we need to do \(x\) amount of times. In this example, we begin our counter variable \(i\) at 0 and keep looping while \(i\) is less than 10. If we cout \(i\) each time, we will get this:

    \begin{lstlisting}[style=terminal] 0 1 2 3 4 5 6 7 8 9 \end{lstlisting}

    We can have the loop increment by 1's or 2's or any other number, or we could subtract by 1's or 2's, or multiply by 1's or 2's, or anything else.


    1. Example: Count down from 10 to 1 by 1 each time
      \begin{lstlisting}[style=cpp] // 10 9 8 7 6 5 4 3 2 1 for ( int i = 10; i > 0; i-- ) { cout << i << "\t"; } \end{lstlisting}


    2. Example: Count from 0 to 14 by 2's
      \begin{lstlisting}[style=cpp] // 0 2 4 6 8 10 12 14 for ( int i = 0; i >= 14; i += 2 ) { cout << i << "\t"; } \end{lstlisting}
    3. Example: Count from 1 to 100 by doubling the number each time
      \begin{lstlisting}[style=cpp] // 1 2 4 8 16 32 64 for ( int i = 0; i >= 100; i *= 2 ) { cout << i << "\t"; } \end{lstlisting}

      For loops will come in even more handy later on once we get to arrays.


  • Nesting loops

    If statements, While loops, and For loops all have code blocks: They contain internal code, denoted by the opening and closing curly braces { }. Within any block of code you can continue adding code. You can add if statements in if statements in if statements, or loops in loops in loops.


    Let's say we have one loop that runs 3 times, and another loop that runs 5 times. If we nest the loops - have one loop within another - then we will end up with an operation that occurs 15 times - \(3 \times 5\). Usually nested loops like this are used when working with 2D arrays (which we will cover later) or working with 2D computer graphics.


    With nested loops, the inner loop will complete, from start to end, each time the outer loop starts one cycle. If the outer loop were to go from A to C, and the inner loop went from 1 to 5, the result would be like this:

    \begin{lstlisting}[style=terminal] A 1 2 3 4 5 B 1 2 3 4 5 \end{lstlisting}

    Example nested loop:

    \begin{lstlisting}[style=cpp] for ( int outer = 0; outer < 3; outer++ ) { for ( int inner = 0; inner < 3; inner++ ) { cout << "OUTER: " << outer << "\t INNER: " << inner << endl; } } \end{lstlisting}


    \begin{lstlisting}[style=terminal] OUTER: 0 INNER: 0 OUTER: 0 INNER: 1 OUTER: 0 INNER: 2 OUTER: 1 INNER: 0 OUTER: 1 INNER: 1 OUTER: 1 INNER: 2 OUTER: 2 INNER: 0 OUTER: 2 INNER: 1 OUTER: 2 INNER: 2 \end{lstlisting}

    See how each line, the INNER number goes up each time and the OUTER number does NOT go up each time… it only goes up once the INNER loop has completed.


  • Review questions:
    1. What are the 3 parts of a for loop?


  • 4.9. Unit 08: C++: Arrays and vectors

    4.9.1. Traditional C arrays


    1. Array basics - what are arrays?

      In C++, arrays are a built-in way to store a series of similar data all under one name.


      Before now, if we wanted to store a list of students in a class (or similar kind of data), we would have to declare a bunch of separate variables and write the same code over and over to manage it:

      \begin{lstlisting}[style=cpp] string student1, student2, student3; cout << "Enter student 1 name: "; cin >> student1; cout << "Enter student 2 name: "; cin >> student2; cout << "Enter student 3 name: "; cin >> student3; \end{lstlisting}

      This would quickly become unmanagable if you were writing a program with tens, hundreds, or thousands of students stored in it. Instead, we can make use of arrays to store a series of related data together.


      \begin{lstlisting}[style=cpp] string students[100]; for ( int i = 0; i < 100; i++ ) { cout << "Enter student " << (i+1) << " name: "; cin >> student[i]; } \end{lstlisting}

      Arrays allow us to operate on the same name (e.g., student), but addressing different elements of the array with an index number. This way, we can write code to act on the data once, just modifying that index to work with different pieces of data.


      Example: student array of size 4:

      Element Rai Anuj Rebekah Rose
      Index 0 1 2 3

      Each item in the array has a corresponding index marking its position in the list, with 0 being the first value. If an array is of size \(n\), then the valid indices are 0 through \(n-1\).

      An element is the information stored at that index position, which is essentially a single variable in an array of variables.


    2. Declaring arrays

      In C++, we declare an array similarly to how we declare a variable, except that we need to specify an array size during declaration:

      \begin{lstlisting}[style=cpp] // An array of size 100 string students[100]; \end{lstlisting}

      Or, if we already have data to put into it, we can initialize it with an initializer list. Then the array will be sized at however many items you give it.

      \begin{lstlisting}[style=cpp] // An array of size 4 string students[] = {"Rai", "Anuj", "Rebekah", "Rose"}; \end{lstlisting}


      1. Size must be known at compile-time

        Traditional C-style arrays must have its size be defined during its declaration and the array cannot be resized during the program's execution. Because the array size can't change, and because we may need to know the size of the array throughout the program, we will generally use a named constant to store the size of the array.

        \begin{lstlisting}[style=cpp] const int MAX_STUDENTS = 100; string students[MAX_STUDENTS]; \end{lstlisting}


      2. A variable to store the # of items in the array

        Because an array's size cannot be changed after its declaration, it often becomes necessary to overshoot the amount of spaces we need in the array so that we always have enough room for our data. Perhaps a school's classrooms range from 20 to 70 seats, so we would want to declare the array of the biggest size so that we don't run out of space. Because of this, not all spaces in the array may be taken up at any given time.

        C++ doesn't have a function to directly get the amount of elements in an array, so generally when declaring an array we need to also have an associated variable to track how many items we've stored in the array.

        \begin{lstlisting}[style=cpp] const int MAX_STUDENTS = 100; // total array size int studentCount = 0; // how many elements string students[MAX_STUDENTS]; // array declaration students[0] = "Rai"; // setting up first student studentCount++; // adding 1 to student count \end{lstlisting}


      3. Array data types

        Arrays can be declared with any data type. To the computer, we are just declaring \(n\) amount of some variable, and it takes care of putting all the \(n\) variables back-to-back in memory.


      4. Valid indices

        As stated earlier, if an array is of size \(n\), then its valid indices are 0 to \(n-1\). In most computer languages, arrays and lists start at index 0 and go up from there, meaning to count for items we have "0, 1, 2, 3".


        A common source of program crashes is going outside the bounds of an array! This happens if you try to access an invalid index, such as student[-1] or student[100] (for an array of size 100; valid indices are 0-99).


    3. Accessing array elements via index

      After we've declared an array, we can treat its elements like normal variables, storing data within it and accessing that data. Each one can be accessed via its index (position in the array) and the subscript operator: [].

      In math, you might be used to these subscripts:

      \[ a_n = a_{n-1} + 2 \]

      But with C++, subscripts look like this:

      a[n] = a[n-1] + 2

      So, declaring an array and accessing its values can look like this:

      \begin{lstlisting}[style=cpp] string courses[4]; courses[0] = "CS 134"; courses[1] = "CS 200"; courses[2] = "CS 210"; courses[3] = "ASL 120"; cout << "First course: " << courses[0] << endl; \end{lstlisting}

      Or, with modern C++ (from 2011 and later) you can initialize an array with an initializer list, {}:

      \begin{lstlisting}[style=cpp] string courses[4] = { "CS 134", "CS 200", "CS 210", "ASL 120" }; cout << "First course: " << courses[0] << endl; \end{lstlisting}


      It's common for array names to be plural - it is a structure that stores multiple items - multiple courses, multiple products, multiple grades, etc. So, to be clear, it is best to give your arrays plural names: courses, products, grades, instead of singular.


      1. Accessing indices with variables

        Since the array index is always an integer, we could use a variable to determine which item in an array to modify - such as asking the user which item they want to edit.

        \begin{lstlisting}[style=cpp] cout << "Edit which item? (0-9): "; cin >> itemIndex; cout << "Enter price for item: "; cin >> prices[ itemIndex ]; \end{lstlisting}


    4. Using for loops with arrays

      Using for loops is the most common way to iterate over all the data in an array, setting data or accessing data. Have an array of size \(n\)? We want to iterate from i = 0 to \(n-1\), going up by 1 each time.


      1. Design pattern: Asking the user to enter all elements

        We can iterate over all the items in an array and have the user enter information for each element by using a loop. Since the first index is 0, we sometimes just add +1 to the index for the user's benefit, since people generally aren't used to lists starting at 0.

        \begin{lstlisting}[style=cpp] const int TOTAL_ITEMS = 10; float prices[TOTAL_ITEMS]; for ( int i = 0; i < TOTAL_ITEMS; i++ ) { cout << "Enter price for item " << (i+1) << ": "; cin >> prices[i]; } \end{lstlisting}


      2. Design pattern: Displaying all items in an array

        We can display all the elements of an array by using a loop as well, though we usually don't want to show all elements of the array - usually just the items we know we're storing data in. Recall that we usually will have an extra integer variable to count how many items have actually been stored in the array, which is different from the total array size.

        \begin{lstlisting}[style=cpp] const int MAX_STUDENTS = 100; int studentCount = 0; string students[MAX_STUDENTS]; // (...Let's say 20 students were added here...) // Iterate from index 0 to 19, since we have stored // 20 students so far. for ( int i = 0; i < studentCount; i++ ) { cout << "Student " << (i+1) << " is " << students[i] << endl; } \end{lstlisting}

        You can also use a range-based for loop in versions of C++ from 2011 or later:

        \begin{lstlisting}[style=cpp] for ( auto & student : students ) { cout << student << endl; } \end{lstlisting}


    5. Parallel arrays

      Let's say we're writing a simple restaurant program where we need a list of dishes and their prices together. Later on, we will write our own data type using structs and classes to keep these items together. But for now, we would implement this relationship by keeping track of two separate arrays with the data we need.

      \begin{lstlisting}[style=cpp] const int MAX_DISHES = 20; int dishCount = 0; // Information about a dish string dishNames[MAX_DISHES]; float dishPrices[MAX_DISHES]; bool dishVegetarian[MAX_DISHES]; // ... Let's say we created some dishes here... // Display the menu cout << "What would you like to order?" << endl; for ( int i = 0; i < dishCount; i++ ) { cout << "Dish #" << i << ":" << endl; cout << "* Name: " << dishNames[i] << endl; cout << "* Price: $" << dishPrices[i] << endl; if ( dishVegetarian[i] ) { cout << "* Is vegetarian" << endl; } cout << endl; } // Get the index of dish they want int whichDish; cout << "Selection: "; cin >> whichDish; \end{lstlisting}


    6. Arrays as arguments

      they could potentially take up a lot of memory. Because of this, passing an array as a pass-by-value parameter would be inefficient - remember that pass-by-value means that the parameter is copied from the caller argument.

      C++ automatically passes arrays around as pass-by-reference instead. You don't have to inclue the & symbol in your parameter list for an array, it just happens! But - keep in mind that any problems with pass-by-reference also apply to arrays. If you want to pass an array to a function but you don't want the data changed, then you would need to mark that array parameter as const.

      \begin{lstlisting}[style=cpp] void DisplayAllItems( const string arr[], int size ) { for ( int i = 0; i < size; i++ ) { cout << arr[i] << endl; } } \end{lstlisting}

      When using an array as a parameter, you don't have to hard-code a size to it. You can leave the square brackets empty (but you DO need square brackets to show that it's an array!) and then pass any array (with matching data type) to the function. However, you will also want to have an int parameter to pass the size of the array as well.


    7. Array management functionality

      Since arrays require quite a bit of management to work with, you could implement some basic functions to do this management, instead of having to re-write the same code over and over. For example…


      1. Clear array

        Sets all elements of this string array to an empty string and resets the elementCount to 0 afterwards.

        \begin{lstlisting}[style=cpp] void Clear( string arr[], int & elementCount ) { for ( int i = 0; i < elementCount; i++ ) { arr[i] = ""; } elementCount = 0; } \end{lstlisting}


      2. Display all elements

        Shows all the elements of an array.

        \begin{lstlisting}[style=cpp] void Display( const string arr[], int elementCount ) { for ( int i = 0; i < elementCount; i++ ) { cout << i << "\t" << arr[i] << endl; } } \end{lstlisting}


      3. Add new element to array

        Often in our programs we will only set up one item at a time (perhaps when selected from a menu). This means we need to get the data for the array and figure out where in the array it will go.

        \begin{lstlisting}[style=cpp] void AddItem( string arr[], int & elementCount ) { cout << "Enter new element: "; cin >> arr[ elementCount ]; elementCount++; } \end{lstlisting}

        For an array, elementCount starts at 0 when the array is empty. This also happens to be the index where we will insert our first element - at 0.

        Index 0 1 2 3

        Once we add our first element, our elementCount will be 1, and the next index to insert data at will also be 1.

        Element Cats      
        Index 0 1 2 3

        Then, elementCount will be 2, and the next index to insert at will be 2.

        Element Cats Dogs    
        Index 0 1 2 3

        Because of this, the elementCount variable both tells us how many items have been stored in the array and what is the next index to store new information at.


    8. Multidimensional arrays

      We can also declare multidimensional arrays, such as 2D or 3D arrays. As with a 1D array, there is just one data type that all the elements share.

      \begin{lstlisting}[style=cpp] string spreadsheet[32][32]; // rows and columns int vertices[4][4][4]; // x, y, z \end{lstlisting}

      Let's say we wanted to turn a day planner into a program. Perhaps we originally stored the day plan like this:

      Day Time Task
      Monday 8:00 Work meeting with Bob
      Monday 13:00 Project review
      Tuesday 10:00 Customer meeting
      Tuesday 12:00 Crying in car
      Wednesady 14:00 Sprint Retrospective


      We can convert this into a 2D array of strings (the "task"), with one dimension being for "day of the week" and the other dimension being for "hour of the day"…

      \begin{lstlisting}[style=cpp] int DAYS_OF_WEEK = 7; int HOURS_IN_DAY = 24; string todo[ DAYS_OF_WEEK ][ HOURS_IN_DAY ]; \end{lstlisting}

      We could ask the user what day they want to set a task for, and if they type "Sunday" that could translate to 0, and "Saturday" could translate to 6 (or however you want to organize your week)…

      Sunday Monday Tuesday Wednesday Thursday Friday Saturday
      0 1 2 3 4 5 6

      We could ask them next for what hour the task is at, and that can map to the second index: "0" for midnight, "8" for 8 am, "13" for 1 pm, and so on to 23.


      With this information, we can get the user's todo task and store it at the appropriate indices:

      \begin{lstlisting}[style=cpp] int day, hour; cout << "Enter the day:" << endl; cout << "0. Sunday \n" << "1. Monday \n" << "2. Tuesday \n" << "3. Wednesday \n" << "4. Thursday \n" << "5. Friday \n" << "6. Saturday \n"; cout << "Day: "; cin >> day; cout << "Enter the hour (0 to 23): "; cin >> hour; cout << "Enter your task: "; cin >> todo[ day ][ hour ]; \end{lstlisting}

      With the user's week planned out, you could then display it back to the user by using a nested for loop: One loop for the day, one loop for the hour.

      \begin{lstlisting}[style=cpp] cout << "YOUR SCHEDULE" << endl; for ( int day = 0; day < DAYS_OF_WEEK; day++ ) { for ( int hour = 0; hour < HOURS_IN_DAY; hour++ ) { cout << day << ", " << hour << ": " << todo[ day ][ hour ] << endl; } } \end{lstlisting}

      Though you'd probably want to do some extra formatting; such as determining that if the day is 0, then write "Sunday" instead of the number "0".


    9. Review questions:
      1. Do all items in an array need to be the same data type in C++?
      2. What is an element of an array?
      3. What is an index?
      4. The subscript operator is…
      5. What code would you write to display the item at position 0 in an array?
      6. What code would you write to display the item at position 2 in an array?
      7. Given an array of size \(n\), the valid indices of the array are…
      8. How do you iterate over all elements of an array?


    4.9.2. Dynamic arrays - Memory allocation with pointers

    1. Dynamic array

      We can use Dynamic Arrays to allocate space for an array at run-time, without having to know or hard-code the array size in our code. To do this, we need to allocate memory on the heap via a pointer.


      1. Creating a dynamic array

        We don't have to know the size of the array at compile-time, so we can do things like ask the user to enter a size, or otherwise base its size off a variable.

        \begin{lstlisting}[style=cpp] int size; cout << "Enter size: "; cin >> size; string* products = new string[size]; \end{lstlisting}


      2. Setting elements of the array

        We can access elements of the dynamic array with the subscript operator, as before. However, we won't know the size of the array unless we use the size variable, so it'd be better to use a for loop to assign values instead of this example:

        \begin{lstlisting}[style=cpp] products[0] = "Pencil"; products[1] = "Eraser"; products[2] = "Pencil case"; products[3] = "Pencil sharpener"; products[4] = "Ruler"; \end{lstlisting}


      3. Iterating over the array

        Accessing elements of the array and iterating over the array is done the same way as with a traditional array.

        \begin{lstlisting}[style=cpp] for ( unsigned int i = 0; i < size; i++ ) { cout << i << ". "; // Display index cout << products[i] << endl; // Display element at that index } \end{lstlisting}


      4. Freeing the memory when done

        Before your pointer loses scope we need to make sure to free the space that we allocated:

        \begin{lstlisting}[style=cpp] delete [] products; \end{lstlisting}


      5. "Resizing" the array

        When memory is allocated for an array we must know the entire size at once because all of the array's elements are contiguous in memory. Because of this, we don't technically "resize" a dynamic array, instead we allocate more space elseware and copy the data over to the new array. Here are the steps:


        One: Allocate space for a new, bigger array

        \begin{lstlisting}[style=cpp] string* newArray = new string[ size + 10 ]; \end{lstlisting}


        Two: Copy the data from the old array to the new array

        \begin{lstlisting}[style=cpp] for ( unsigned int i = 0; i < size; i++ ) { newArray[i] = products[i]; } \end{lstlisting}


        Three: Free the space at the old address

        \begin{lstlisting}[style=cpp] delete [] products; \end{lstlisting}


        Four: Update the main array pointer to the new address

        \begin{lstlisting}[style=cpp] products = newArray; // Point to same address \end{lstlisting}


        Five: Update your size variable

        \begin{lstlisting}[style=cpp] size = size + 10; \end{lstlisting}


    2. Review questions:
      1. How do you allocate memory for an array via a pointer?
      2. How do you deallocate memory for a dynamic array?
      3. What are the steps to "resize" a dynamic array?


    4.9.3. STL array and vector

    1. C++ Standard Template Library: Arrays

      Documentation: https://cplusplus.com/reference/array/array/


      If we put #include <array> at the top of our file, we can use an array object instead of a traditional array to store data. They are basically interchangible, ecxept the array object gives us access to the .size() function, making our job slightly easier. However, the array still can't be resized.


      1. Creating an STL array
        \begin{lstlisting}[style=cpp] array products; \end{lstlisting}


      2. Setting elements of the array
        \begin{lstlisting}[style=cpp] products[0] = "Pencil"; products[1] = "Eraser"; products[2] = "Pencil case"; products[3] = "Pencil sharpener"; products[4] = "Ruler"; \end{lstlisting}


      3. Iterating over the array
        \begin{lstlisting}[style=cpp] for ( unsigned int i = 0; i < products.size(); i++ ) { cout << i << ". "; // Display index cout << products[i] << endl; // Display element at that index } \end{lstlisting}


    2. C++ Standard Template Library: Vectors

      Documentation: https://cplusplus.com/reference/vector/vector/


      The C++ Standard Template Library contains a special structure called a vector. A vector is a class (something we'll learn about later) and it is implemented on top of a dynamic array (which we will learn about later with pointers). Basically, it's a resizable array and it has functionality to make managing data a bit more managable.

      Generally, in Computer Science curriculum, we teach you how to build data structures (structures that store data) like vectors, lists, and other items because it's important to know how they work (thus why we're covering arrays), but for your own projects and in the real world, you would probably use a vector over an array.


      1. Declaring a vector

        Vectors are a type of templated object, meaning it can store any data type - you just have to specify what kind of type the vector stores. The format of a vector declaration looks like this:

        \begin{lstlisting}[style=cpp] // Declaring vectors vector students; vector prices; \end{lstlisting}


      2. Adding data

        You can add data to a vector by using its push_back function, passing the data to add as the argument:

        \begin{lstlisting}[style=cpp] vector students; students.push_back( "Rai" ); \end{lstlisting}


      3. Getting the size of the vector

        The size function will return the amount of elements currently stored in the vector.

        \begin{lstlisting}[style=cpp] cout << "There are " << students.size() << " students" << endl; \end{lstlisting}


      4. Clearing the vector

        You can erase all the data in a vector with the clear function:

        \begin{lstlisting}[style=cpp] students.clear(); \end{lstlisting}


      5. Accessing elements by index

        Accessing an element at some index looks just like it does with an array:

        \begin{lstlisting}[style=cpp] cout << "Student: " << students[0] << endl; \end{lstlisting}


      6. Iterating over a vector

        You can use a for loop to iterate over all the elements of a vector, similar to an array:

        \begin{lstlisting}[style=cpp] cout << "Students:" << endl; for ( int i = 0; i < students.size(); i++ ) { cout << i << "\t" << students[i] << endl; } \end{lstlisting}

        You can also use C++11 style range-based for loop if you don't need the index. It allows you to iterate over all the elements of students, using an alias of student for each element.

        \begin{lstlisting}[style=cpp] for ( auto & student : students ) { cout << student << endl; } \end{lstlisting}


    3. Review questions:
      1. How do you declare an STL array object?
      2. How do you declare an STL vector object?
      3. How do you add new items to a vector object?


    4.10. Unit 09: C++: Branching

    4.10.1. If statements

    1. Branching

      Branching is one of the core forms of controlling the flow of the program. We ask a question, and based on the result we perhaps do this code over here or maybe that code over there - the program results change based on variables and data accessible to it.

      We will mostly be using if / else if / else statements, though switch statements have their own use as well. Make sure to get a good understanding of how each type of branching mechanism "flows".


      1. If statements

        If statements (usually the general term encompassing if / else if / else as well) are a way we can ask a question and respond: If \(a\) is less than \(b\) then… or if \(a\) is greater than \(c\) then… Otherwise do this default thing…

        Let's look at some examples while ironing out how it works.


        For a basic if statement, we use the syntax:

        \begin{lstlisting}[style=cpp] // Do things 1 if ( CONDITION ) { // Do things 2-a } // Do things 3 \end{lstlisting}

        The CONDITION will be some boolean expression. If the boolean expression result is true, then any code within this if statement's code block (what's between \* and \*) will get executed. If the result of the expression is false, then the entire if statement's code block is skipped and the program continues.


        \begin{lstlisting}[style=cpp] cout << "Bank balance: " << balance; if ( balance < 0 ) { cout << " (OVERDRAWN!)"; } cout << " in account #" << accountNumber << endl; \end{lstlisting}

        Output with balance = -50

        \begin{lstlisting}[style=terminal] Bank balance: -50 (OVERDRAWN!) in account #1234 \end{lstlisting}

        Output with balance = 100

        \begin{lstlisting}[style=terminal] Bank balance: 100 in account #1234 \end{lstlisting}
        • The special message "OVERDRAWN!" only gets displayed when the balance is less than 0.
        • The following cout that gives the account number is displayed in all cases.


      2. If/Else statements

        In some cases, we will have code that we want to execute for the false result as well. For an if/else statement, either the if code block will be entered, or the else code block will be.

        NOTE: The else statement NEVER has a CONDITION.

        \begin{lstlisting}[style=cpp] // Do things 1 if ( CONDITION ) { // Do things 2-a } else { // Do things 2-b } // Do things 3 \end{lstlisting}

        The else block is executed when the if check fails. If the CONDITION is false, we can use DeMorgan's Laws to figure out what the program's state is during the else.


        \begin{lstlisting}[style=cpp] cout << "Enter your age: "; cin >> age; if ( age < 18 ) { result = "can't vote"; } else { result = "can vote"; } cout << "Result: " << result << endl; \end{lstlisting}

        If the age is less than 18, it will set the result variable to "can't vote". If that boolean expression is false, that means age is \(\geq\) 18, and then it will set the result to "can vote". Finally, either way, it will display "Result: " with the value of the result variable.


      3. If/Else if/Else statements

        In some cases, there will be multiple scenarios we want to search for, each with their own logic. We can add as many else if statements as we want - there must be a starting if statement, and each else if statement will have a condition as well.

        We can also end with a final else statement as a catch-all: if none of the previous if / else if statements are true, then else gets executed instead. However, the else is not required.

        \begin{lstlisting}[style=cpp] // Do things 1 if ( CONDITION1 ) { // Do things 2-a } else if ( CONDITION2 ) { // Do things 2-b } else if ( CONDITION3 ) { // Do things 2-c } else { // Do things 2-d } // Do things 3 \end{lstlisting}


        \begin{lstlisting}[style=cpp] cout << "Enter grade: "; cin >> grade; if ( grade >= 90 ) { letterGrade = 'A'; } else if ( grade >= 80 ) { letterGrade = 'B'; } else if ( grade >= 70 ) { letterGrade = 'C'; } else if ( grade >= 60 ) { letterGrade = 'D'; } else { letterGrade = 'F'; } cout << "Grade: " << letterGrade << endl; \end{lstlisting}

        With this example, I'm first checking if the grade is 90 or above. If it is, then I know the letter grade is 'A'.

        However, if it's false, it will go on and check the next else if statement. At this point, I know that since

        \(grade \geq 90\) was FALSE

        that means

        \(grade < 90\) is TRUE.

        Since the next statement checks if

        \[grade \geq 80\]

        if this one is TRUE, I know that:

        \(grade < 90\) AND \(grade \geq 80\)


    2. Nesting if statements

      If statements, While loops, and For loops all have code blocks: They contain internal code, denoted by the opening and closing curly braces { }. Within any block of code you can continue adding code. You can add if statements in if statements in if statements, or loops in loops in loops.

      Nesting an if statement within another if statement basically gives you a boolean expression with an AND.


      \begin{lstlisting}[style=cpp] if ( wantsBeer ) { if ( age >= 21 ) { GiveBeer(); } } \end{lstlisting}

      Equivalent logic:

      \begin{lstlisting}[style=cpp] if ( wantsBeer && age >= 21 ) { GiveBeer(); } \end{lstlisting}

      Whether you implement some logic with nested if statements, or with if / else if statements using AND operations is a matter of design preference- in some cases, one might be cleaner than the other, but not always.

      If you have a statement like this:

      \begin{lstlisting}[style=cpp] if ( conditionA ) { if ( conditionB ) { Operation1(); } else { Operation2(); } } \end{lstlisting}

      It could be equivalently described like this:

      \begin{lstlisting}[style=cpp] if ( conditionA && conditionB ) { Operation1(); } else if ( conditionA && !conditionB ) { Operation2(); } \end{lstlisting}


    4.10.2. Switch statements

    1. Switch statements

      Switch statements are a special type of branching mechanism that only checks if the value of a variable is equal to one of several values. Switch statements can be useful when implementing a menu in a program, or something else where you only have a few, finite, discrete options.

      In C++, switch statements only work with primitive data types, like integers and chars - not strings.

      \begin{lstlisting}[style=cpp] switch ( VARIABLE ) { case VALUE1: // Do thing break; case VALUE2: // Do thing break; default: // Default code } \end{lstlisting}

      With a switch statement, each case is one equivalence expression. The default case is executed if none of the previous cases are.


      \begin{lstlisting}[style=cpp] case VALUE1: // equivalent to: if ( VARIABLE == VALUE1 ) \end{lstlisting}
      \begin{lstlisting}[style=cpp] case VALUE2: // equivalent to: if ( VARIABLE == VALUE2 ) \end{lstlisting}
      \begin{lstlisting}[style=cpp] default: // equivalent to: else \end{lstlisting}


      The default case is not required, just like how the else clause is not required in an if statement.


      The break; statement

      The end of each case should have a break; statement at the end. If the break is not there, then it will continue executing each subsequent case's code until it does hit a break.

      This behavior is "flow-through", and it can be used as a feature if it matches the logic you want to write.


      Variables inside cases

      If you're declaring a variable within a case statement, you need to enclose your case with curly braces { }, otherwise you'll get compiler errors:

      \begin{lstlisting}[style=cpp] switch ( operation ) { case 'A': { float result = num1 + num2; cout << "Result: " << result << endl; } break; } \end{lstlisting}


      Calculator example:

      Perhaps you are implementing a calculator, and want to get an option from the user: (A)dd, (S)ubtract, (M)ultiply, or (D)ivide. You could store their choice in a char variable called operation and then use the switch statement to decide what kind of computation to do:

      \begin{lstlisting}[style=cpp] switch ( operation ) { case 'A': // if ( operation == 'A' ) result = num1 + num2; break; case 'S': // else if ( operation == 'S' ) result = num1 - num2; break; case 'M': // else if ( operation == 'M' ) result = num1 * num2; break; case 'D': // else if ( operation == 'D' ) result = num1 / num2; break; } cout << "Result: " << result << endl; \end{lstlisting}


      Flow-through example:

      Sometimes you want to check if your variable equals a value "x" or "y", and execute the same code for each. You can use flow-through in this case. If no break; is given for a specific case, then it will continue to execute code for the following case until a break; is found.

      \begin{lstlisting}[style=cpp] char choice; cout << "Do you want to quit? (Y/N): "; cin >> choice; switch ( choice ) { case 'Y': case 'y': done = true; break; case 'N': case 'n': done = false; break; default: cout << "Unknown selection!" << endl; } \end{lstlisting}


    4.11. Unit 10: C++: Searching and sorting

    4.11.1. Searching

    We're going to keep this section short for now because we're mostly going to be focusing on sorting algorithms.


    1. Linear search

      When we're searching for items in an unsorted linear structure there's not much we can do to speed up the process. We can basically either start at the beginning and move forward, or start and the end and move backward, checking each item in the structure for what you're looking for.

      \begin{lstlisting}[style=cpp] template int LinearSearch( const vector& arr, T findme ) { int size = arr.size(); for ( int i = 0; i < size; i++ ) { if ( arr[i] == findme ) { return i; } } return -1; // not found } \end{lstlisting}
      • We begin at the first index 0 and iterate until we hit the last index. Within the loop, if the element at index i matches what we're looking for, we return this index.
      • If the loop completes and we haven't returned an index yet that means we've searched the entire structure and have not found the item. In this case, it is not in the structure and we can throw an exception to be dealt with elseware or return something like -1 to symbolize "no valid index".

      This search algorithm's growth rate is \(O(n)\) – the more items in the structure, the time linearly increases to search through it. Not much we can do about that, which is why we have different types of data structures that sort data as it is inserted - more on those later on.


    2. Binary search

      OK, but what if the structure is sorted?

      We're going to be learning about sorting algorithms, so what if we happen to have a structure that is sorted? How can we more intelligently look for some value in the structure?

      Let's say we have a simple array like this:

      Value: "aardvark" "bat" "cat" "dog" "elephant" "fox"
      Index: 0 1 2 3 4 5

      And we want to see if "dog" is in the array. We could investigate what the first item is (Hm, starts with an "a") and the last item ("f"), and realize that "d" is about halfish way between both values. Maybe we should start in the middle and move left or right?

      • Index 0 is "aardvark". Index 5 is "fox". Middle value \(\frac{0+5}{2}\) is 2.5 (or 2, for integer division). What is at position 2? – "cat". If arr[2] \(<\) findme, move left (investigate arr[1] next) Or if arr[2] \(>\) findme, move right (investigate arr[3] next).
      • "d" is greater than "c" so we'll move right… Index 3 gives us "dog" - we've found the item! Return 3.

      In this case, we basically have two iterations of a loop to find "dog" and return its index. If we were searching linearly, we would have to go from 0 to 1 to 2 to 3, so four iterations.

      This still isn't the most efficient way to search this array - just starting at the midpoint and moving left or moving right each time. However, we can build a better search that imitates that first step: Checking the mid-way point each time.

      Here is the code:

      \begin{lstlisting}[style=cpp] template int BinarySearch( vector arr, T findme ) { int size = arr.size(); int left = 0; int right = size - 1; while ( left <= right ) { int mid = ( left + right ) / 2; if ( arr[mid] < findme ) { left = mid + 1; } else if ( arr[mid] > findme ) { right = mid - 1; } else if ( arr[mid] == findme ) { return mid; } } return -1; // not found } \end{lstlisting}

      With the binary search we look at the left-most index, right-most index, and mid-point. Each iteration of the loop, we look at our search value findme – is its value greater than the middle or less than the middle?


      1. Example: Binary search on a sorted array

        Let's say we have this array, and we are searching for 'p'.

        Value: 'a' 'c' 'e' 'h' 'i' 'k' 'm' 'o' 'p' 'r'
        Index: 0 1 2 3 4 5 6 7 8 9


        Step 1: left is at 0, right is at 9, mid is \(\frac{0+9}{2}\) = 4 (integer division).

        Value: 'a' 'c' 'e' 'h' 'i' 'k' 'm' 'o' 'p' 'r'
        Index: 0 1 2 3 4 5 6 7 8 9
          left       mid         right

        Next we compare i to 'p'. 'p' comes later in the alphabet (so p > i), so next we're going to change the left value to look at mid+1 and keep right as it is.


        Step 2: left is at 5, right is at 9, mid is \(\frac{5+9}{2} = \frac{14}{2}\) = 7.

        Value: 'a' 'c' 'e' 'h' 'i' 'k' 'm' 'o' 'p' 'r'
        Index: 0 1 2 3 4 5 6 7 8 9
                    left   mid   right

        Now we compare the item at arr[mid] 'o' to what we're searching for ('p'). p > o so we adjust our left point again to our current midpoint.


        Step 3: left is at 7, right is at 9, mid is \(\frac{7+9}{2} = \frac{16}{2}\) = 8.

        Value: 'a' 'c' 'e' 'h' 'i' 'k' 'm' 'o' 'p' 'r'
        Index: 0 1 2 3 4 5 6 7 8 9
                        left mid right

        Now we compare the item at arr[mid] ('p') to what we're searching for ('p'). The values match! So the result is mid as the index where we found our item.

        Each step through the process we cut out half the search area by investigating mid and deciding to ignore everything either before it (like our example) or after it. We do this every iteration, cutting out half the search region each time, effectively giving us an efficiency of \(O(log(n))\) - the inverse of an exponential increase.


    4.11.2. Sorting

    I'll update the text here later for next semester but I never liked sorting algorithms. I always found the approach to studying them really tedious in uni. I'm not going to make you have to figure out these algorithms yourself - the algorithms are online.

    I'm just going to give you the code and we can visually step through how they work. It's possible you'll be asked to implement some sorting algorithms in a job interview if the company is really annoying, but for the most part you're going to be using sorting algorithms already implemented in your day-to-day life rather than implementing these yourself from scratch each time.

    You'll find animations and stuff on the class webpage that hopefully illustrate it better than we could in a typewritten format.


    Sorting algorithm efficiency (From https://www.bigocheatsheet.com/)

    Algorithm Best time Average time Worst time
    Bubble Sort \(\Omega(n)\) \(\Theta(n^{2})\) \(O(n^{2})\)
    Insertion Sort \(\Omega(n)\) \(\Theta(n^{2})\) \(O(n^{2})\)
    Selection Sort \(\Omega(n^{2})\) \(\Theta(n^{2})\) \(O(n^{2})\)
    Merge Sort \(\Omega(n log(n))\) \(\Theta(n log(n))\) \(O(n log(n))\)
    Quick Sort \(\Omega(n log(n))\) \(\Theta(n log(n))\) \(O(n^{2})\)


    1. Bubble Sort
      \begin{lstlisting}[style=cpp] template void BubbleSort( vector& arr ) { for ( int i = 0; i < arr.size() - 1; i++ ) { for ( int j = 0; j < arr.size() - i - 1; j++ ) { if ( arr[j] > arr[j+1] ) { swap( arr[j], arr[j+1] ); } } } } \end{lstlisting}


    2. Insertion Sort
      \begin{lstlisting}[style=cpp] template void InsertionSort( vector& arr ) { size_t arraySize = arr.size(); size_t i = 1; while ( i < arraySize ) { int j = i; while ( j > 0 && arr[j-1] > arr[j] ) { swap( arr[j], arr[j-1] ); j = j - 1; } i = i + 1; } } \end{lstlisting}


    3. Selection Sort
      \begin{lstlisting}[style=cpp] template void SelectionSort( vector& arr ) { int arraySize = arr.size(); for ( size_t i = 0; i < arraySize - 1; i++ ) { int minIndex = i; for ( size_t j = i + 1; j < arraySize; j++ ) { if ( arr[j] < arr[minIndex] ) { minIndex = j; } } if ( minIndex != i ) { swap( arr[i], arr[minIndex] ); } } } \end{lstlisting}

    4. Merge Sort
      \begin{lstlisting}[style=cpp] // Declarations template void MergeSort( vector& arr ); template void MergeSort( vector& arr, int left, int right ); template void Merge( vector& arr, int left, int mid, int right ); // Definitions template void MergeSort( vector& arr ) { MergeSort( arr, 0, arr.size() - 1 ); } template void MergeSort( vector& arr, int left, int right ) { if ( left < right ) { int mid = ( left + right ) / 2; MergeSort( arr, left, mid ); MergeSort( arr, mid+1, right ); Merge( arr, left, mid, right ); } } template void Merge( vector& arr, int left, int mid, int right ) { const int n1 = mid - left + 1; const int n2 = right - mid; vector leftVec; vector rightVec; for ( int i = 0; i < n1; i++ ) { leftVec.push_back( arr[left + i] ); } for ( int j = 0; j < n2; j++ ) { rightVec.push_back( arr[mid + 1 + j] ); } int i = 0; int j = 0; int k = left; while ( i < n1 && j < n2 ) { if ( leftVec[i] <= rightVec[j] ) { arr[k] = leftVec[i]; i++; } else { arr[k] = rightVec[j]; j++; } k++; } while ( i < n1 ) { arr[k] = leftVec[i]; i++; k++; } while ( j < n2 ) { arr[k] = rightVec[j]; j++; k++; } } \end{lstlisting}

    5. Quick Sort
      \begin{lstlisting}[style=cpp] // Declarations template void QuickSort( vector& arr ); template void QuickSort( vector& arr, int low, int high ); template int Partition( vector& arr, int low, int high ); // Definitions template void QuickSort( vector& arr ) { QuickSort( arr, 0, arr.size() - 1 ); } template void QuickSort( vector& arr, int low, int high ) { if ( low < high ) { int partIndex = Partition( arr, low, high ); QuickSort( arr, low, partIndex - 1 ); QuickSort( arr, partIndex + 1, high ); } } template int Partition( vector& arr, int low, int high ) { T pivotValue = arr[high]; int i = low - 1; for ( int j = low; j <= high - 1; j++ ) { if ( arr[j] <= pivotValue ) { i++; swap( arr[i], arr[j] ); } } swap( arr[i+1], arr[high] ); return i + 1; } \end{lstlisting}


    4.12. Unit 11: Tech Literacy: Current trends in tech

    4.12.1. AI


    4.13. Unit 12: Tech Literacy: Object Oriented Programming


    4.13.1. Programming paradigms

    Programming paradigms (pronounced "pair-uh-dimes") are ways we can classify different programming languages based on features they have available or the style programs are written. Different paradigms have popped up over the life of computers as programming languages grow and evolve.

    • Machine code: At the beginning, computers were programmed with machine code, where you work directly with instructions supported by the hardware - for example, add, sub, storing data in registers, and other relatively simple commands.
    • Procedural Languages: Eventually, those commands were abstracted into higher-level languages, where one command in, say, C, could "translate" to several machine-code instructions. Languages like C, Fortran, Algol, BASIC, and C are known as Procedural Languages, where these programs would describe a procedure to follow and instructions are executed one-at-a-time in a specific order (top-to-bottom, or calling a function and returning).
    • Object Oriented Programming: Languages like C supported our basic control flow and using functions, but did not include classes - a way to make more sophisticated data types. A class is a structure that can store its own member variables and member functions. A variable whose data type is from some defined class is known as an object.

    There are other programming paradigms, but we are going to focus on Object Oriented Programming (OOP) now since it's a large part of using C++ and other languages like Java, C#, and Python.


    4.13.2. Introduction to Object Oriented Programming


    Object Oriented Programming (or "OOP") is probably one of the most popular ways to design and implement software these days. In programming, an object is some sort of structure that stores its own data (variables) and functionality (functions). We try to design our programs as a collection of objects that interact with each other to get some job done.

    In C++ and many other languages functions always end with parentheses ( ), which is how you can quickly identify them. Sometimes, there is data in the parentheses - these are input parameters. Functions can also return data as well, so each interaction between objects can pass inputs between objects, and return data between objects.


    1. Design ideals

      Designing programs in an OOP style helps us pursue certain design goals:

      • Abstraction: Hiding complexity in the design, creating an "interface" for the user, generalizing functionality to a more "digestible" form. Think of a button on any device: If you open up the device, there's a lot actually going on, but we just see the simple button and don't have to worry about the rest.
        • Certain functions are made public that other programmers can use to interface with the object.
        • The other programmers don't need to worry about the inner-workings of the object in order to use it.
        • The developer of the class can modify how the internals work without breaking the public interface.
        • Helps protect the data within the class from being accessed or modified by things it shouldn't.
      • Encapsulation: Also goes along with creating an "interface", though in this regard we are encapsulating related pieces together. We can store data (variables) with the functions that operate on that data (functions) all within a class object.
      • Loose coupling: Ideally, different objects in a program shouldn't have their functionality tied to other objects too closely; we want to reduce inter-dependence between objects. When objects are more independent from each other, they are loosely coupled.
      • High cohesion: When we design our objects, we shouldn't just throw everything and the kitchen sink into one object. To design an object with high cohesion means that everything inside the object belongs in that object. Reduce the clutter.


    2. Inheritance and composition


      Sometimes we have multiple objects that are similar but still have different sets of data (member variables) - think of a File, how we might have an Image File, Sound File, Video File… Each file has a name, file extension, and size, but the actual file contents are different.

      And sometimes we have an object that is best represented by being "inside" another object - think of a House with an array of Room objects.

      These are the two ideas between inheritance, an "is-a" relationship, and composition, a "has-a" relationship.


      With inheritance:

      • Variables and functions from a class can be inherited by child classes. This means that the child class will have these same variables and functions, without having to re-write it all.
      • We use this to create specialized versions of some generic object, like a GameObject, PlayerObject, and NPCObject, or a Shape, Square, and Circle.

      With composition:

      • One class is a member variable of another class, and is generally a private member.
      • Often this means that the internal class can't be accessed by outside functions, and the "containing" class needs to have some kind of interface layer to allow interactions with that internal item.
      • Some people argue that you should prefer using composition over inheritance because the act of composing another class keeps it "modularized"; that class' features are encapsulated within a variable, and not more inherited variables added onto the pile-o-variables a class has.


    3. Accessibility levels

      When we're designing our objects we don't want to give unrestricted access to every part of the program. We generally create a class and it is responsible for certain things, including modifying its own data. This helps us protect the integrity of the data. Each member variable and function belonging to a class can be marked as one of these three accessibility levels:

      Any part of the program can access these members. This is usually used for the member functions of a class.
      These members can only be accessed by the class itself, from within its functions.
      Similar to private except that classes that inherit from the class we're defining will also have access to protected members. More on this when we cover inheritance.


    4.13.3. Modeling C++ classes using UML

    UML (Unified Modeling Language) is a way to diagram classes, their member variables and functions (methods), and relationships between those classes. It is meant as a language-agnostic way to describe your codebase or how something should be designed.

    1. Describing a single object

      A UML diagram for a single class looks like this:

      - x : int
      - y : int
      - image : Texture
      + Setup() : void
      + Move(velX: float, velY: float): void
      + BeginJump() : void
      + BeginAttack() : void
      + Draw(screen:Window) : void

      Here's how to read it:

      • The TOP region is the name of the class.
      • The MIDDLE region is its member variables.
      • The BOTTOM region is its member methods/functions.
      • The - minus sign signifies private accessibility level, which means these members can only be accessed by this class' functions.
      • The + plus sign signifies public accessibility level, which means these members can be accessed by this class' functions or any functions external to it (like belonging to another class, or in main()).
      • A # pound sign signifies protected accessibility level (used with inheritance, which we will cover more later).


    2. Describing relationships between objects

      UML diagrams are also used to show the relationship between classes.


      In a diagram that shows a relationship between objects you will see arrows going between classes.

      • A line coming FROM a class and ending in a triangle arrow to another class shows an inheritance relationship, with the former inheriting from the latter.
      • A line coming FROM a class and ending in a diamond shape to another class shows a composition relationship, with the former being contained within the latter.

      Using UML diagrams can be (relatively) quick to write out and to read, compared to just giving someone a .h header file or all the code itself. Often, companies will have some kind of global UML diagram of all of the components in their codebase and how they interact - developers are expected to update this diagram as they add/remove classes or members of classes.


    4.14. Unit 13: C++: Classes and Inheritance

    4.14.1. Classes

    1. Structs
      1. Structs vs. Classes

        Structs in C++ have all the same functionality of a Class, but are generally used design-wise to group a few variables together, maybe some functions, into a simple structure. A class, on the other hand, is usually used for much bigger and more complex objects.

        In C++, the only difference between Structs and Classes are default accessibility - if you don't specify the accessibility of your variables/functions within a struct, they are public by default. This means that anything in the program can access those variables/functions. For Classes, everything is private by default - only that Class itself can use the variables/functions.


      2. Declaring a struct

        Struct declarations go in header (.h) files. Usually the file name should reflect the name of the struct itself, and the file guard labels should also match.

        \begin{lstlisting}[style=cpp] #ifndef _STRUCTNAME #define _STRUCTNAME struct STRUCTNAME { int var; void Func(); }; #endif \end{lstlisting}

        Design-wise, structs should only contain a small amount of data. While structs can contain functions, it is generally better to create a class if you find yourself needing functions.

        An example of a small struct would be grouping \(x\) and \(y\) coordinates together in a Coordinate Pair…

        \begin{lstlisting}[style=cpp] struct CoordinatePair { float x, y; }; \end{lstlisting}

        Sometimes we need to group some basic variables together. Structs are great for this.

        \begin{lstlisting}[style=cpp] struct Rectangle { float left, right, top, bottom; }; \end{lstlisting}


      3. Declaring object variables

        Once a struct has been declared in a program, you can then create a variable with that data type. To access the internal variables of the struct, you use the variable's name followed by the dot operator . and then the name of the member variable.

        \begin{lstlisting}[style=cpp] // Declare two variables CoordinatePair point1, point2; cout << "Enter the x y coordinates for the first point: "; cin >> point1.x >> point1.y; cout << "Enter the x y coordinates for the second point: "; cin >> point2.x >> point2.y; float slope = ( point2.y - point1.y ) / ( point2.x - point1.x ); cout << "The slope is: " << slope << endl; \end{lstlisting}

        We will have more examples during the section on Classes, since that's mostly what we will be using. Again, structs are useful for combining a small amount of member variables together under one name, usually used for structures for math (coordinates, rectangles, etc.) but more sophisticated objects ought to be created with a class.


    2. Classes

      Traditionally, a struct is used to create small objects that join a few variables together. Classes are much more heavily used in C++ and is the back-bone of Object Oriented Programming. There is a lot we can do with classes, but for now we are just going to look at the basics.

      A class declaration looks just like a struct declaration except that we use the keyword class. Take note that with a struct and class declaration, we must end the closing curly brace with a semi-colon.

      \begin{lstlisting}[style=cpp] class Player { public: void SetPosition( int newX, int newY ); void Move(); private: int x, y; }; \end{lstlisting}


      1. Accessibility

        We can define our member variables and functions with three different levels of accessibility, dictating where these members can be accessed throughout the program:

        Any part of the program can access these members. This is usually used for the member functions of a class.
        These members can only be accessed by the class itself, from within its functions.
        Similar to private except that classes that inherit from the class we're defining will also have access to protected members. More on this when we cover inheritance.


      2. Header and Source files

        When we are creating a class, we generally will put the class declaration within its own header file. Header files end with .h or .hpp - I tend to use .hpp since we're using C++ and I like to explicitly state this is a "C++ header"; the .h extension was also used in C. However, the C++ Core Guidelines document says to:

        NL.27: Use a .cpp suffix for code files and .h for interface files

        Reason It's a longstanding convention. But consistency is more important, so if your project uses something else, follow that.

        (From https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#reason-451)


        Class declaration goes in Rectangle.h (or Rectangle.hpp):

        \begin{lstlisting}[style=cpp] #ifndef _RECTANGLE_H #define _RECTANGLE_H class Rectangle { public: void SetPosition( int newX, int newY ); void SetDimensions( int newWidth, int newHeight ); private: int x, int y, int width, int height; }; #endif \end{lstlisting}


        Class function definitions go in Rectangle.cpp:

        \begin{lstlisting}[style=cpp] #include "Rectangle.h" void Rectangle::SetPosition( int newX, int newY ) { x = newX; y = newY; } void Rectangle::SetDimensions( int newWidth, int newHeight ) { width = newWidth; height = newHeight; } \end{lstlisting}

        In our source file (.cpp), we need to make sure to include the header that goes with our class so it knows about the class declaration. Then, we can define the member functions here.

        Note that when we're defining the functions outside of the class declaration, we must prefix the function name with the class name, followed by the scope resolution operator ::

        \begin{lstlisting}[style=cpp] void Rectangle::SetPosition( int newX, int newY ) \end{lstlisting}

        This is the standard way C++ files are organized - for each class we create, we create a header and a source file for it.


      3. Additional context with classes
        • What is #ifndef?
          • In C++, when we #include "Rectangle.h" in a different source file, the compiler essentially copy-pastes the code from the included file into the includer file. Because of this, if multiple files are #include "Rectangle.h"-ing (or any other header), the same code in that header gets copied multiple times, making the compiler think you've declared the same class over and over.
          • #ifndef, #define, and #endif are preprocessor commands used by the compiler. We are essentially saying "if-not-defined _RECTANGLE_H, define _RECTANGLE_H, … … end-if.", preventing the compiler from copying the same file twice.
        • Defining member functions inside the class declaration
          • It is completely possible to define our member functions inside the class declaration, getting rid of the need for the .cpp file. However, this does end up being treated differently by the compiler - writing our class this way makes the functions inline… Basically, instead of having a separate function that the compiler will mark as "call this", it will copy the contents of the inlined function to the function call, basically replacing the call with the contents of the function. I haven't written much about how the compiler works since that's a more specialized topic and we don't need to worry about it at this stage of learning C++. This is just here for your own info.
        • Should you define functions in the .h or the .cpp?
          • It is standard to put class declarations and function declarations in .h files, and the function/method definitions in the .cpp files. You should follow this best practice.
        • What is a Function vs. Method?
          • A method is a word that means "member function". In Java and C#, the term method is used instead of function, since you physically cannot have functions defined outside of a class in those languages.
          • I tend to stick with the term "member function", but if I write "method", it means that, whereas a "function" would be a standalone function elseware in the program.


      4. Getters and Setters

        In Object Oriented Programming, we generally want to hide the inner-workings of a class from the outside world (other functions and other classes). If everything were exposed, then other parts of the program could make changes to our class and it could be difficult to track down all those modifying locations (this, in particular, is a nightmare at a job with a large codebase).

        We generally write all our member variables as private - accessible only to the class' member functions themseves - and use public member functions to interface with those variables as needed.

        For example, in our Rectangle class, we might have a function to set up the entire Rectangle all at once…

        \begin{lstlisting}[style=cpp] void Rectangle::Setup( int newX, int newY, int newWidth, int newHeight ) { x = newX; y = newY; width = newWidth; height = newHeight; } \end{lstlisting}

        … or just a couple things at a time …

        \begin{lstlisting}[style=cpp] void Rectangle::SetPosition( int newX, int newY ) { x = newX; y = newY; } \end{lstlisting}
        Or, we might want to just set one member variable's value.

        In this case, we write a member function called a setter (aka mutator) that is responsible for setting a member variable's value:

        \begin{lstlisting}[style=cpp] void Rectangle::SetX( int newX ) { x = newX; } \end{lstlisting}

        The good thing about having setters instead of directly updating the x variable is that we can add error checks in our setter. Say, perhaps, that we don't want x to be negative, so we validate the input before changing it…

        \begin{lstlisting}[style=cpp] void Rectangle::SetX( int newX ) { if ( newX >= 0 ) { x = newX; } } \end{lstlisting}

        If somewhere else in the program tries to set a negative value for the x variable, it will just ignore that command. (We could also throw an exception or display an error message or set a default value - it's up to your design.)

        Likewise, sometimes we want to access

        those member variables to see what values they store. In this case, we write Getter member functions that are responsible for returning a copy of the data (or, in some cases, a reference to it - but that's a design decision).

        \begin{lstlisting}[style=cpp] int Rectangle::GetX() { return x; } \end{lstlisting}

        Getters are also handy for formatting output prior to returning it, or doing some other operation before returning something. Let's say we have a member function for a Student class, and a GetName function is going to combine their names and return it together:

        \begin{lstlisting}[style=cpp] int Student::GetFullName() { return lastName + ", " + firstName; } \end{lstlisting}

        To summarize…

        • Setters: Sets the value of a member variable. Generally, return type is void and there is one paramete for the new value. void SetThing( int newValue );
        • Getters: Returns the value of a member variable. Generally, return type matches that variable, and there are no parameters. =int GetThing(); =


      5. Constructors and Destructors

        Constructors and Destructors are special types of member functions in a class.

        • Constructor:
          • Runs automatically as soon as a new object is declared.
          • Can declare more than one constructor.
          • No return type
          • Constructor name must match name of the class.
        • Destructor:
          • Runs automatically as soon as a new object is destroyed.
          • Can only have one destructor.
          • No return type
          • Destructor name \underline=must= match name of the class, prefixed with a tilde \~.

        Example: Text file wrapper

        Let's say we're writing a class that works with a text file.

        When the object is created, the constructor will open the file and get it ready to write to. With various member functions we can write to that text file as the program is running. Then, when the program ends and the object is destroyed, it will automatically close the text file for us.

        Class declaration:

        \begin{lstlisting}[style=cpp] class Logger { public: // constructors Logger( string filename ); Logger(); // destructor ~Logger(); // other method void Write( string text ); private: ofstream m_output; }; \end{lstlisting}

        We have two constructors: one where we pass in a filename for a file to open, and one where we don't. In the second case, we can use a default file name.

        Context: Why "m_" with the variable?

        In some places, it is standard to prefix private member variables with an underscore (_output) or (m_output). I tend to use the latter when writing private member variables of a class. The "m" stands for "member".

        The constructor definitions could look like this:

        \begin{lstlisting}[style=cpp] Logger::Logger( string filename ) { m_output.open( filename ); } Logger::Logger() { m_output.open( "log.txt" ); } \end{lstlisting}

        The Write function could be used to write information to that text file, and could be implemented like this:

        \begin{lstlisting}[style=cpp] void Logger::Write( string text ) { m_output << text << endl; } \end{lstlisting}

        And then the destructor would be used to close up the file at the end:

        \begin{lstlisting}[style=cpp] Logger::~Logger() { m_output.close(); } \end{lstlisting}

        Now, we don't have to manually deal with file operations since this class wraps that functionality and deals with it for us.

        To use the program, we just declare the object variable:

        \begin{lstlisting}[style=cpp] #include "Logger.hpp" int main() { // At this point, // a constructor is called automatically Logger log( "logfile.txt" ); // Writing to the text file log.Write( "Hello!" ); log.Write( "How are you?" ); // Program ends here. The destructor // is called automatically when the log variable // goes out of scope and is destroyed. return 0; } \end{lstlisting}

        It can often be handy to overload our constructors so that we can initialize our objects in several different ways.


        1. Types of constructors
          1. Default Constructors

            A default constructor is a constructor with no parameters in it. This will be called when a variable of this class type is declared with no constructor explicitly called.

            Usually, a default constructor would be used to initialize variables to default values, and if your class contains pointers, this constructor should initialize those pointers to point to nullptr.

            \begin{lstlisting}[style=cpp] class MyClass { public: MyClass() // Default constructor { m_value = 0; } private: int m_value; }; \end{lstlisting}

            When we create a new object of this type like this, the default constructor will be called:

            \begin{lstlisting}[style=cpp] MyClass classVar; \end{lstlisting}


          2. Parameterized Constructors

            Parameterized Constructors take in one or more parameters to help initialize the member variables of the object. We can have 0, one, or multiple parameterized constructors for our class.

            \begin{lstlisting}[style=cpp] class MyClass { public: MyClass() { // Default m_value = 0; } MyClass( int value ) { // Parameterized m_value = value; } // etc }; \end{lstlisting}

            When we instantiate our object, we can pass in argument(s) in order to call the parameterized version of the constructor:

            \begin{lstlisting}[style=cpp] MyClass classVar( 100 ); \end{lstlisting}

            If you declare a parameterized constructor but not a default constructor, then the C++ compiler will assume that you don't want an object to be declared with the default constructor. This means, you would only be able to declare the variable with an explicit call to the constructor and with arguments.

            If this isn't the desired design, make sure to include a default constructor, even if you just leave it blank.


          3. Copy Constructors

            A copy constructor takes in another object of the same type as its parameter and uses this to copy over members from the parameter to the new object.

            \begin{lstlisting}[style=cpp] class MyClass { public: MyClass() // Default { m_value = 0; } MyClass( int value ) // Parameterized { m_value = value; } MyClass( const MyClass& other ) // Copy { m_value = other.m_value; } private: int m_value; }; \end{lstlisting}

            In this case, we might already have an object of this type available, and when we are creating a new object, we want to make a copy of the old object:

            \begin{lstlisting}[style=cpp] MyClass classVar( 100 ); MyClass anotherOne( classVar ); // Copy \end{lstlisting}
            • Design: When a class has multiple member variables, it is up to us to decide which variables get copied over during this operation. There could be some design cases where all information is copied over except certain fields (maybe a unique customerID or a name).
            • Default copy constructor: If you don't explicitly declare a copy constructor, the C++ compiler will provide one for the class behind-the-scenes. This implicit copy constructor will only do shallow copies.


            Ways to copy:

            • A Shallow Copy is where values of variables are copied over. This is generally fine for any sort of non-pointer-based variables. If the class contains a pointer that is pointing to some address, the shallow-copy of the pointer will point to the same address.
            • A Deep Copy is where values are copied over like with a shallow copy, but also will allocate new memory for a dynamic array (if the class has one) in order to copy over values of the element of the array to the new class copy.


            Example of a shallow copy:


            With the implicit copy constructor, any pointers in the copied version will be pointing to the same address as in the original. If the class contains a dynamic array, both the copy and the original will end up pointing to the same address of the array in memory.


            Example of a deep copy:


            A new block of memory has been allocated for the int * numArr. The values from InstanceA's numArr would be copied to InstanceB's numArr via a for loop during construction.


    3. Additional class concepts
      1. Const member methods

        When we declare a class' member function as const, we are saying that this function should not ever change any values of any member variables of this class. This can be handy for methods like a Display() where we just want to output member variables but should never change them.

        \begin{lstlisting}[style=cpp] class Coordinates { public: int GetX() const; // Can't change m_x or m_y int GetY() const; // Can't change m_x or m_y void SetX( int val ); void SetY( int val ); private: int m_x, m_y; }; \end{lstlisting}

        The function definition will also need to have this const marked at the end of the function header as well.

        \begin{lstlisting}[style=cpp] int Coordinates::GetX() const { return m_x; } \end{lstlisting}


      2. this

        Within our class methods, we can explicitly refer to the object we are currently working with as this. this is a pointer, so it is pointing to a memory address. Any member of the class can also be accessed via the this pointer:

        \begin{lstlisting}[style=cpp] class MyClass { public: void A() { cout << "Hello!" << endl; } void B() { this->A(); cout << this->var << endl; } void C() { A(); cout << var << endl; } private: int var; }; \end{lstlisting}

        In this example, methods B() and C() do the same thing, but B() explicitly uses this.


    4. Review questions:
      1. True or false: A class can have member variables and functions (methods).
      2. Class declarations go in what kind of file?
      3. Class function (method) definitions go in what kind of file?
      4. A class' public members can be accessed by…
      5. A class' protected members can be accessed by…
      6. A class' private members can be accessed by…
      7. When defining a function that is a member of a class, the function name needs to be prefixed with…
      8. What does a getter (accessor) function do?
      9. What does a setter (mutator) function do?
      10. When does a constructor function run?
      11. When does a destructor function run?
      12. The constructor and destructor name must match what?


    4.14.2. Inheritance


    Inheritance is where one class inherits some or all member variables and functions from some parent class. Certain "traits" are passed on, and the child class can have additional member variables and functions defined, making it a more specialized version of the parent class.

    1. Reusing functionality

      Let's say we're designing an operating system that will store files. We can think about what all files have in common, and we can figure out what is different between different types of files. Any commonality could go in a base class (aka parent class).

      So, a generic File class might have contain variables and functions like:

      - m_filename : string
      - m_extension : string
      - m_fileSize : size_t
      - m_creationDate : DateTime
      + CreateFile(...) : void
      + RenameFile(...) : void
      + GetSize() : size_t
      + GetPath() : string

      Then we could have specialized file classes that inherit from the original File, such as TextFile, ImageFile, SoundFile, and so on. These would inherit all the common attributes of its parent (File), but each would have additional variables and methods that are suited specifically to its own specialization.

      • TextFile: m_textContent, Print()
      • ImageFile: m_pixels[][], Draw(), EditPixel( x, y )
      • SoundFile: m_audioSample, m_length, Play(), Pause(), Stop()


    2. Example: The iostream and fstream family


      Part of the ios family. You can see the full library's family tree at http://www.cplusplus.com/reference/ios/

      One family we've already been using are our console input/output streams, cin and cout, and our file input/output streams, ifstream and ofstream. Working with each of these works largely the same way.

      When we overload the << and >> stream operators, we use a base type of istream and ostream so that our class can handle cin / cout AND ifstream / ofstream, as well as any other streams in that family tree.


    3. Inheritance (Is-A) vs. Composition (Has-A)

      Another way we think about inheritance is that one class "is-a" type of other class.

      Car is-a vehicle:

      \begin{lstlisting}[style=cpp] class Car : public Vehicle { // etc. }; \end{lstlisting}

      Whereas Composition, where one class contains another class as a member variable object, is known as a "has-a" relationship.

      Car has-an engine:

      \begin{lstlisting}[style=cpp] class Car { private: Engine engine; }; \end{lstlisting}

      When is composition more appropriate than inheritance? This is a design question and it can really depend on how the designer feels about each one.


    4. Example: Game objects

      For example, when writing a game, I find inheritance handy for creating game objects. A BaseObject can contain everything that's in common between all objects (characters, items, tiles, etc.), such as:


      Any items that don't animate, don't move, and just sit there in the level could be instantiated as a simple BaseObject and it would be fine.

      # m_position : Coordinate
      # m_sprite : Sprite
      # m_name : string
      + Setup(...)  
      + SetTexture(...)  
      + Update(...)  
      + SetPosition(...)  
      + Draw(...)  

      Then, let's say we want to build a 2D game level and each level is made up of a 2D array of tiles. Tiles will be very similar to objects, but maybe we want more information stored in a tile. We could then inherit from the BaseObject…



      The Tile class would have all the public and protected members from its parent, plus any new member variables and methods we declare within this class.

      Tile Inherits from BaseObject
      - m_isSolid : bool
      - m_doesDamage : bool

      For the game characters, there would be two different types usually: characters that the players control and characters that the computer controls. Character could be its own base-class as well, implementing anything a character can do, with a Player and NPC (non-player-character) classes inheriting from Character.

      Character Inherits from BaseObject
      # m_speed : int
      # m_direction : Direction
      # m_animFrame : float
      # m_maxFrames : float
      + Move(...)  
      + Animate(...)  



      Player Inherits from Character
      - m_score : int
      - m_experience : int
      - m_level : int
      + HandleKeyboard(...)  
      + LevelUp(...)  

      The Player class would be a specialized type of Character that can be controled via the keyboard (or some other input device), as well as have information that a non-player-character generally has, such as a score or a level.



      NPC Inherits from Character
      - m_difficulty : int
      - m_isFriendly : bool
      + SetGoal(...)  
      + DecideNextAction(...)  

      Likewise, the NPC class is a specialization of Character as well, but with special functionality and attributes of a character in the game controlled by the computer itself. This could include some form of AI to help the NPC decide how to behave.


      Game object family:


      With this family of game objects, we could also write functions that work on all types of game objects, such as checking if there's a collision between items, because they all have a common parent.



    5. Implementing inheritance

      In C++ a class can inherit from one or more other classes. Note that Java and C# do not support multiple inheritance directly, if you end up switching to those languages. Design-wise, however, it can be messy to inherit from more than one parent and as an alternative, you might find a composition (has-a) approach a better design.


    6. Inheriting from one parent

      To inherit from one other class in C++, all you need to do is add ": public OTHERCLASS" after the "class CLASSNAME" at the beginning of your class declaration. With a public inheritance (the most common kind), the child class will inherit all public and protected members of the parent class.

      \begin{lstlisting}[style=cpp] // File is the parent class File { protected: string name; string extension; size_t filesize; }; // TextDocument is the child class TextDocument : public File { protected: string textContents; /* Also inherits these members from File: string name; string extension; size_t filesize; ,*/ }; \end{lstlisting}

      Context: The Parent Class is often known as the superclass and the Child Class is often known as the subclass, particularly from the Java perspective.


    7. Inheriting from multiple parents

      You can also have a class inherit from multiple parents, bringing in public/protected members from all parent classes, but again this can muddle your program's design somewhat and is generally pretty uncommon.

      \begin{lstlisting}[style=cpp] class AnimationObject // Parent A { public: void Animate(); protected: int totalFrames; int currentFrame; }; class PhysicsObject // Parent B { public: void Fall(); void Accelerate(); protected: float velocity; float acceleration; }; class PlayerCharacter : public AnimationObject, public PhysicsObject { public: void HandleKeyboard(); protected: string name; }; \end{lstlisting}


    8. Private, Public, and Protected
      Member access

      Remember that we can declare our member variables and methods as private and public, but we can also make items protected. Protected members are similar to private, except that protected members will be inherited by child classes - private members do not get inherited.

      Access Class' methods Childrens' methods Outside functions
      public Accessible Accessible Accessible
      protected Accessible Accessible Not accessible
      private Accessible Not accessible Not accessible

      Inheritance style
      You can also use public, protected, and private when inheriting other classes. You probably won't need to ever do a protected or private inheritance.
      • public inheritance: Child class inherits public and protected members from the parent.
      • protected inheritance: Child class inheirits public and protected members and turns them into protected members.
      • private inheritance: Child class inherits public and protected members and turns them into private members.

      This could be used if, for some reason, you want a child class to inherit certain members but don't want "grandchildren" to have access to those members as well.


    9. Function Overriding

      When a child class inherits from a parent class, the parent class' public and protected methods are passed down to the child and these functions are still callable for objects of the child type.

      If we would like, the child class can also override any methods from the parent. This means that we write a new version of the function with the same return type and parameter list, and when that function is called from the child class, the child class' version will be called instead of the parents'.

      Let's say we're writing a quizzer program that will support differnet question types. We can write a base "Question" class with whatever would be in common between all Questions:

      \begin{lstlisting}[style=cpp] class Question { public: Question( string q, string a ) { question = q; answer = a; } void AskQuestion() { cout << question << endl; string playerAnswer; cin >> playerAnswer; if ( playerAnswer == answer ) { cout << "Right!" << endl; } else { cout << "Wrong." << endl; } } protected: string question; string answer; }; \end{lstlisting}

      We can then inherit from our Question class to make different types of quiz questions: Multiple choice, true/false, and so on. Adding additional functionality means that we might want to rewrite how AskQuestion() works - so we can.

      This also means that everything in our Question family has a similar interface - create a question, set it up, and then call AskQuestion() no matter what kind of question it is.

      \begin{lstlisting}[style=cpp] class MultipleChoiceQuestion : public Question { public: void DisplayQuestion() { cout << question << endl; for ( int i = 0; i < 4; i++ ) { cout << i << ". " << answerChoices[i] << endl; } int playerAnswer; cin >> playerAnswer; if ( answerChoices[ playerAnswer ] == answer ) { cout << "Right!" << endl; } else { cout << "Wrong." << endl; } } protected: string answerChoices[4]; }; \end{lstlisting}


    10. Calling the parents' version of a method

      In some cases, perhaps the parent version of a method has some common functionality we will need no matter what version in the family we're using, but the child versions of the methods add on to that functionality. We can directly call the parent's version of some method from within a child's method by explicitly calling the method with the parent class name and the scope resolution operator ::.

      \begin{lstlisting}[style=cpp] class Lion { public: void Activities() { cout << "Hunt" << endl; cout << "Eat" << endl; cout << "Sleep" << endl; } }; class HouseCat : public Lion { public: void Activities() { Lion::Activities(); cout << "Talk to human" << endl; cout << "Use catbox" << endl; } }; \end{lstlisting}

      For this example, the HouseCat does everything the Lion does and adds a few activities to the list. We don't have to re-write the same Activities from Lion - we can just call the parent's version of the method directly with Lion::Activities();.


    11. Constructors and Destructors in the family

      We often use constructors to initialize member variables for a class, and when a child is inheriting its parents' member variables, we want to make sure we're not forgetting to still initialize those variables.

      We can call the parent's constructor from the child's constructor as well, but we do it via the initializer list of a constructor - a little bit of code after the constructor's function header that can be used to initialize variables and call the parent constructor.

      \begin{lstlisting}[style=cpp] class Person { public: Person( string name ) { m_name = name; } protected: string m_name; }; class Student : public Person { public: Student( string name, string major ) : Person( name ) // Calling the parent ctor { m_major = major; } protected: string m_major; }; \end{lstlisting}

      (Note: "ctor" is short for "constructor")

      We can also initialize variables through the initializer list as well:

      \begin{lstlisting}[style=cpp] class Student : public Person { public: Student( string name, string major ) : Person( name ), m_major( major ) { // nothing else to do now! } protected: string m_major; }; \end{lstlisting}


    4.15. Unit 14: C++: Strings and File I/O

    4.15.1. Strings


    A string is a special data type that really is just an array of char variables. A string has a lot going on behind-the-scenes, and it also has a set of functions you can use to do some common operations on a string - finding text, getting a letter at some position, and more.

    Note that everything with strings is case-sensitive. A computer considers the letter 'a' and 'A' different, since they are represented by different number codes. Keep that in mind for each of the string's functions.

    Strings as arrays

    When we declare a string like this:

    \begin{lstlisting}[style=cpp] string str = "pizza"; \end{lstlisting}

    what we have behind-the-scenes is an array like this:

    Value: 'p' 'i' 'z' 'z' 'a'
    Index: 0 1 2 3 4

    Declaring a string actually gives us an array of char variables. We can access the string as a whole by using the string variable's name (str), or access one char at a time by treating str like an array.

    1. Subscript operator - get one char with [ ]

      We can access each letter of the string directly with the subscript operator, just like an array:

      \begin{lstlisting}[style=cpp] cout << str[0] << endl; // Outputs p cout << str[1] << endl; // Outputs i cout << str[2] << endl; // Outputs z cout << str[3] << endl; // Outputs z cout << str[4] << endl; // Outputs a \end{lstlisting}

      Because we can act on a string like an array, this means we can also use a variable to access an arbitrary index of a character in the array…

      \begin{lstlisting}[style=cpp] int i; cout << "Get which letter? "; cin >> i; cout << str[i]; \end{lstlisting}

      Or even iterate over the string with a for loop

      \begin{lstlisting}[style=cpp] for ( int i = 0; i < str.size(); i++ ) { cout << i << " = " << str[i] << endl; } \end{lstlisting}

      Additionally, strings have a set of functions that we can use to manipulate, search, and otherwise work with them.

      String functionality

    2. Size of the string

      size_t size() const;

      The string's size() function will return the size of the string - how many characters are stored in the string. The size_t data type is just a type of integer - an unsigned integer, because sizes cannot be negative amounts.

      Documentation: https://www.cplusplus.com/reference/string/string/size/

      Example: Outputting a string's length
      Let's write a little program that asks the user to enter some text, and then outputs the length of the string:
      \begin{lstlisting}[style=cpp] string text; cout << "Enter some text: "; getline( cin, text ); cout << "That string is " << text.size() << " characters long!" << endl; \end{lstlisting}

      When the user enters a line of text, it will count all characters (including spaces) in the string, so the text "cats dogs" would be 9 characters long.

      \begin{lstlisting}[style=terminal] Enter some text: cats dogs That string is 9 characters long! \end{lstlisting}


      Example: Counting z's
      If we wanted to use a for loop to iterate over all the letters of an array, we could! Perhaps we want to count the amount of z's that show up:
      \begin{lstlisting}[style=cpp] string text; int zCount = 0; cout << "Enter some text: "; getline( cin, text ); // Iterate from i=0 to the size of the string (not-inclusive) for ( unsigned int i = 0; i < text.size(); i++ ) { // If this letter is a lower-case z or upper-case Z if ( text[i] == 'z' || text[i] == 'Z' ) { // Add one to z count zCount++; } } // Display the result cout << "There were " << zCount << " z(s) in the string!" << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Enter some text: The wizard fought a zombie lizard There were 3 z(s) in the string! \end{lstlisting}


    3. Concatenating strings with +

      We can use the + operator to add strings together as well. This is called concatenation.

      Let's say we have two strings we want to combine - favoriteColor and petName, we can use the concatenation operator + to build a new string, superSecurePassword.

      \begin{lstlisting}[style=cpp] string favoriteColor = "purple"; string petName = "Luna"; string superSecurePassword = favoriteColor + petName; cout << superSecurePassword << endl; // = purpleLuna \end{lstlisting}


      We can also add onto strings by using the += operator. Let's say you're building a string over time in a program, and want to append parts separately.

      \begin{lstlisting}[style=cpp] string pizzaToppings = ""; // Later on... pizzaToppings += "Buffalo sauce, "; // Later on... pizzaToppings += "Cheese, "; // Later on... pizzaToppings += "Pineapple"; // Later on... cout << pizzaToppings << endl; \end{lstlisting}

      At the end of the program, the value of pizzaToppings would be:

      "Buffalo sauce, Cheese, Pineapple"

    4. Finding text with find()

      size_t find (const string& str, size_t pos = 0 ) const;

      The find function can be used to look for a substring in a bigger string. If the substring is found, its position is returned. Otherwise, the value of string::npos is found.

      When a starting pos is included, it only begins the search at that position. If left off, it defaults to 0 (the start of the string).

      Documentation: https://www.cplusplus.com/reference/string/string/find/

      So when we want to search a string for some text, we can call it like bigString.find( findMeString ), and that function call will return an unsigned integer: the location of the findMeString within bigString, or the value of string::npos when it is not found.

      \begin{lstlisting}[style=cpp] string str = "this was written during the 2021 winter storm make it stop please."; string findMe = "winter"; size_t position = str.find( findMe ); cout << "The text \"" << findMe << "\" was found at position " << position << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] The text "winter" was found at position 33 \end{lstlisting}

    5. Finding substrings with substr()

      string substr (size_t pos = 0, size_t len = npos) const;

      Returns a string within the string, starting at the position pos provided, and with a length of len.

      Documentation: https://www.cplusplus.com/reference/string/string/substr/

      With the substr() function, we can pull part of a string out, using a starting point and a length.

      \begin{lstlisting}[style=cpp] string text = "Name: Bob"; int start = 6; int length = 3; string name = text.substr( start, length ); cout << "Extracted \"" << name << "\"." << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Extracted "Bob". \end{lstlisting}


    6. Comparing text with compare()

      int compare (const string& str) const;

      This compares the string with str and returns an integer:

      • \(0\) is returned if both strings are the same.
      • \(< 1\) (a negative number) is returned if the caller string is "less-than" the str string.
      • \(> 1\) (a positive number) is returned if the caller string is "greater-than" the str string.

      One character is "less than" another if it comes before, and it is "greater than" if it comes after, alphabetically.

      (Remember that lower-case and upper-case letters are considered separate, so comparing 'a' to 'A' would actually return a positive number.)

      Documentation: https://www.cplusplus.com/reference/string/string/compare/

      \begin{lstlisting}[style=cpp] string first; string second; cout << "Enter first string: "; cin >> first; cout << "Enter second string: "; cin >> second; int order = first.compare( second ); cout << endl << "Result: " << order << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Enter first string: apple Enter second string: banana Result: -1 \end{lstlisting}


    7. Inserting text into a string with insert()

      = string& insert (sizet pos, const string& str);=

      This function will take the calling string and modify it by inserting the string str at the position pos.

      Documentation: https://www.cplusplus.com/reference/string/string/insert/

      \begin{lstlisting}[style=cpp] string text = "helloworld"; cout << "Original text: " << text << endl; int start; string insertText; cout << "Enter text to insert: "; getline( cin, insertText ); cout << "Enter position to insert: "; cin >> start; text = text.insert( start, insertText ); cout << endl << "String is now: " << text << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Original text: helloworld Enter text to insert: -to the- Enter position to insert: 5 String is now: hello-to the-world \end{lstlisting}

    8. Erasing a chunk of text with erase()

      string& erase (size_t pos = 0, size_t len = npos);

      This function will return a string with a portion erased, starting at position pos and pulling out a length of len.

      Documentation: https://www.cplusplus.com/reference/string/string/erase/

      \begin{lstlisting}[style=cpp] string text = "helloworld"; cout << "Original text: " << text << endl; int start; int length; cout << "Enter position to begin erasing: "; cin >> start; cout << "Enter length of text to erase: "; cin >> length; text = text.erase( start, length ); cout << endl << "String is now: " << text << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Original text: helloworld Enter position to begin erasing: 2 Enter length of text to erase: 5 String is now: herld \end{lstlisting}

    9. Replacing a region of text with replace()

      string& replace (size_t pos, size_t len, const string& str);

      This function is similar to erase, except it will insert the string str in place of the erased text.

      Documentation: https://www.cplusplus.com/reference/string/string/replace/

      \begin{lstlisting}[style=cpp] string text = "helloworld"; cout << "Original text: " << text << endl; int start; int length; string replaceWith; cout << "Enter string to replace with: "; getline( cin, replaceWith ); cout << "Enter position to begin replacing: "; cin >> start; cout << "Enter length of text to replacing: "; cin >> length; text = text.replace( start, length, replaceWith ); cout << endl << "String is now: " << text << endl; \end{lstlisting}
      \begin{lstlisting}[style=terminal] Original text: helloworld Enter string to replace with: BYE Enter position to begin replacing: 2 Enter length of text to replacing: 5 String is now: heBYErld \end{lstlisting}

  • Review questions:
    1. A string is technically an array of…
    2. How would you output the letter at position 0 in a string? At position 2?
    3. What function is used to get the amount of characters in a string?
    4. What operator is used to combine (concatenate) two strings together?
    5. What does the find() function return if the searched-for substring is not found?


  • 4.15.2. File I/O


    1. Output streams

      In C++ we've been using cout to stream information to the console window in our programs. Using cout requires including the iostream library.

      \begin{lstlisting}[style=cpp] cout << "Hello, " << location << "!" << endl; \end{lstlisting}

      Writing out to a text file works in a very similar way. We will need to include the fstream library in order to get access to the ofstream (output-file-stream) object. Streaming out to a file works in the same way as with cout, except that we need to declare a ofstream variable and use it t open a text file.

      \begin{lstlisting}[style=cpp] #include // Console streams #include // File streams using namespace std; int main() { // Console output cout << "Hello, world!" << endl; // File output ofstream outputFile( "file.txt" ); outputFile << "Hello, world!" << endl; outputFile.close(); } \end{lstlisting}

      You can use the output stream operator << to continue chaining together different items - endl=s, string literals in double quotes, variable values, etc. just like with your =cout statements.

      Once the file is closed, you will see the file on your computer, usually the same directory as your .cpp files.

      Different file types…
      Any file type that is a plaintext file can be built as well - .html files, .csv files, heck, even .cpp files. However, generally if you wanted to write a program to output a different file type, you'd use a library to properly convert the data.

      Outputting html data:

      \begin{lstlisting}[style=cpp] #include using namespace std; int main() { ofstream outputFile( "page.html" ); outputFile << "" << endl; outputFile << "

      This is a webpage

      " << endl; outputFile << "

      Hello, world!

      " << endl; outputFile << "" << endl; outputFile.close(); } \end{lstlisting}

      Outputting csv data:

      \begin{lstlisting}[style=cpp] #include using namespace std; int main() { ofstream outputFile( "spreadsheet.csv" ); outputFile << "COLUMN1,COLUMN2,COLUMN3" << endl; outputFile << "cell1,cell2,cell3" << endl; // row 1 outputFile << "cell1,cell2,cell3" << endl; // row 2 outputFile << "cell1,cell2,cell3" << endl; // row 3 outputFile.close(); } \end{lstlisting}

    2. Input streams

      File input streams work just line console input streams. You will need to create a ifstream (input-file-stream) object and open a file, and then you can read in the contents of that file. Files to be read should generally be placed in the same path as your .cpp file, though the working directory on your system may vary.

      \begin{lstlisting}[style=cpp] #include // File streams #include // Strings using namespace std; int main() { string data1, data2; // File input ifstream inputFile( "file.txt" ); inputFile >> data1; // Read one word inputFile.ignore(); // Clear buffer getline( inputFile, data2 ); // Read one line inputFile.close(); } \end{lstlisting}

      Just like with using cin, you can use the input stream operator (>>) and the getline() function with the file streams to get text. You will also need one or more variable to store the text read in.

      1. Reading an entire file
        Reading chunks of data:
        Let's say you have a file full of data to read in. For this example, the file will be a list of numbers that we want to add together. The file might look something like….


        \begin{lstlisting}[style=textfile] 9 15 16 0 10 13 5 16 1 9 2 17 3 3 8 \end{lstlisting}

        In our program, we want to read all the numbers, but to do this, we need to use a loop and read in one number at a time. We can keep a running total variable to keep adding data to the sum as we go. We can use a loop to continue reading while it is successful, using this as the condition: input >> readNumber. This will stop the loop once there's nothing else to read, and it updates the readNumber variable with the input each cycle.

        \begin{lstlisting}[style=cpp] ifstream input( "data.txt" ); int sum = 0; // Sum variable int readNumber; // Buffer to store what we read in // Keep reading while it's possible while ( input >> readNumber ) { sum += readNumber; // Add on to the sum // Output what we did cout << "Read number " << readNumber << ",\t sum is now " << sum << endl; } cout << "FINAL SUM: " << sum << endl; \end{lstlisting}

        The output of this program would look like this:

        \begin{lstlisting}[style=textfile] Read number 9, sum is now 9 Read number 15, sum is now 24 (... etc ...) Read number 3, sum is now 119 Read number 8, sum is now 127 FINAL SUM: 127 \end{lstlisting}
        Reading lines of data:
        In other cases, maybe you're reading in text data from a file and want to read in a full line at a time. We can use a while loop with the getline() function as well to make sure we read each line of a text file:
        \begin{lstlisting}[style=cpp] ifstream input( "story.txt" ); string line; while ( getline( input, line ) ) { cout << line << endl; } \end{lstlisting}

        The output of this program would look like this:

        \begin{lstlisting}[style=textfile] CHAPTER I. Down the Rabbit-Hole Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice "without pictures or conversations?" \end{lstlisting}

    3. Saving and loading data
      1. Parsing files

        Reading in data from a file is one thing, but making sense of what was read in is another. Are you storing saved data from the last session of the program? Are you trying to parse data to crunch? How do you read that data in logically?

        First, if your program is going to be saving output that will need to be read in and made sense of later on, how do you organize the data that's output? It's up to you to make sure to structure the output save data in a consistent and readable way…

        \begin{lstlisting}[style=textfile] SAVEGAME RachelsGame LEVEL 5 GOLD 1000 LOCATION RegnierCenter \end{lstlisting}

        If every save file from the program is formatted in the same way, then when reading the file we can make assumptions…

        • First word: "SAVEGAME" - not important (human readable)
        • Second word: Save game name - store in gameFileName
        • Third word: "LEVEL" - not important (human readable)
        • Fourth word: Player's level - store in level

        …And so on. This could work, but we could also take advantage of those human-readable labels that were added into the file.

        • Read firstWord.
        • If firstWord is "SAVEGAME", then read the next word into gameFileName.
        • Else if firstWord is "LEVEL", then read the next word into level.

        So, let's say we have our four variables for a save game:

        Name Data type
        gameFileName string
        level int
        gold int
        location string

        When we go to save our game file, it would be a simple output like this:

        \begin{lstlisting}[style=cpp] // Save the game ofstream output( "save.txt" ); output << "SAVEGAME " << gameFileName << endl; output << "LEVEL " << level << endl; output << "GOLD " << gold << endl; output << "LOCATION " << location << endl; \end{lstlisting}

        Giving us a save file like:

        \begin{lstlisting}[style=textfile] SAVEGAME MyGame LEVEL 1 GOLD 10 LOCATION OCB \end{lstlisting}

        Then to read it, we could approach it in a couple of different ways. If we assume that the file will always have exactly four lines of data saved and will always be in the same order, we could read it like:

        \begin{lstlisting}[style=cpp] // Load the game string buffer; ifstream input( "save.txt" ); input >> buffer; // ignore SAVEGAME input >> gameFileName; input >> buffer; // ignore LEVEL input >> level; input >> buffer; // ignore GOLD input >> gold; input >> buffer; // ignore LOCATION input >> location; \end{lstlisting}

        Or, if we weren't sure that order these would show up in, we could store the first item read into buffer each time, and based on what that label was ("SAVEGAME", "LEVEL", etc.) we would know what to read next

        \begin{lstlisting}[style=cpp] string buffer; ifstream input( "save.txt" ); while ( input >> buffer ) { if ( buffer == "SAVEGAME" ) input >> gameFileName; else if ( buffer == "LEVEL" ) input >> level; else if ( buffer == "GOLD" ) input >> gold; else if ( buffer == "LOCATION" ) input >> location; } \end{lstlisting}

        If we stepped through this, buffer is always going to store one of the data labels, because after buffer is read, we immediately read the second item in the line of text. Once the second item is read, the next thing to be read will be the next label.

  • Review questions:
    1. What library is required in order to use file I/O in C++?
    2. What data type is used to create a file that inputs (reads in) text from an outside file?
    3. What data type is used to create a file that outputs (writes out) text to an outside file?
    4. How do you write out the string literal "Hello world" to an output file?
    5. How do you write out the value of a variable to an output file?
    6. How do you read in one word from an input file?
    7. How do you read in one line from an input file?


  • 4.16. Unit 15: Tech Literacy: Ethics in tech

    Articles to read:

    Videos to watch:


    4.17. Unit 16: C++: Intro to recursion


    4.17.1. Examples of recursion in math

    Recursion is a manner of solving a problem by breaking it down into smaller pieces - and those smaller pieces are solved in the same way as the big-picture version.

    1. Summation:

      A summation can be broken down into smaller chunks but using the same structure as the original.

      Let's say we have \[ \sum_{i=1}^{6} { i } = 1 + 2 + 3 + 4 + 5 + 6 \]

      The summation can be redefined recursively:

      \[ \sum_{i=1}^{6} { i } = 6 + \sum_{i=1}^{5} { i } \]

      The summation from \(i = 1\) to \(6\) is equivalent to whatever the sum is at \(i=6\), plus the sum from \(i = 1\) to \(5\).

      We can continue this way until we get to a case that we know (e.g., \(\sum_{i=1}^{1} { i }\)).

      • \(\sum_{i=1}^{6} { i } = 6 + \sum_{i=1}^{5} { i }\)
      • \(\sum_{i=1}^{5} { i } = 5 + \sum_{i=1}^{4} { i }\)
      • \(\sum_{i=1}^{4} { i } = 4 + \sum_{i=1}^{3} { i }\)
      • \(\sum_{i=1}^{3} { i } = 3 + \sum_{i=1}^{2} { i }\)
      • \(\sum_{i=1}^{2} { i } = 2 + \sum_{i=1}^{1} { i }\)
      • We know that \(\sum_{i=1}^{1} { i } = 1\), then we move back up to sub out this value.
      Recursive problem      
      A. \[\sum^{6}_{i=1} { i } = 6 + \sum_{i=1}^{5} { i }\] But what is \[\sum_{i=1}^{5} { i }\] ?
      B. \[\sum_{i=1}^{5} { i } = 5 + \sum_{i=1}^{4} { i }\] But what is \[\sum_{i=1}^{4} { i }\] ?
      C. \[\sum_{i=1}^{4} { i } = 4 + \sum_{i=1}^{3} { i }\] But what is \[\sum_{i=1}^{3} { i }\] ?
      D. \[\sum_{i=1}^{3} { i } = 3 + \sum_{i=1}^{2} { i }\] But what is \[\sum_{i=1}^{2} { i }\] ?
      E. \[\sum_{i=1}^{2} { i } = 2 + \sum_{i=1}^{1} { i }\] But what is \[\sum_{i=1}^{1} { i }\] ?
      F. \[\sum_{i=1}^{1} { i } = 1\]      

      Now we start substituting this value back for each step…

      Finding the solution    
      G. \[\sum_{i=1}^{2} { i } =\] \[2 + \sum_{i=1}^{1} { i } =\] \[2 + 1 = 3\]
      H. \[\sum_{i=1}^{3} { i } =\] \[3 + \sum_{i=1}^{2} { i } =\] \[3 + 3 = 6\]
      I. \[\sum_{i=1}^{4} { i } =\] \[4 + \sum_{i=1}^{3} { i } =\] \[4 + 6 = 10\]
      J. \[\sum_{i=1}^{5} { i } =\] \[5 + \sum_{i=1}^{4} { i } =\] \[5 + 10 = 15\]
      K. DONE! \[\sum_{i=1}^{6} { i } =\] \[6 + \sum_{i=1}^{5} { i } =\] \[6 + 15 = 21\]

    2. Factorials:

      With a factorial of \(n\), written \(n!\) the formula to solve this is:

      \[ n! = n \cdot (n-1) \cdot ... \cdot 3 \cdot 2 \cdot 1 \]


      • \(2!\) is \(2 \cdot 1\),
      • \(3!\) is \(3 \cdot 2 \cdot 1\),
      • \(4!\) is \(4 \cdot 3 \cdot 2 \cdot 1\), and so on.

      Additionally, we can break down each of these equations: \(3!\) is equivalent to \(3 \cdot 2!\) \(4!\) is equivalent to \(4 \cdot 3!\) … \(n!\) is equivalent to \(n \cdot (n-1)!\)

      Thinking of breaking down the problem here in this way is looking at it recursively.


    4.17.2. Recursion in programming

    In programming, we usually approach problems iteratively, using a for-loop or a while-loop:

    \begin{lstlisting}[style=cpp] // Iterative solution int Sum( int n ) { int result = 0; for ( int i = 1; i <= n; i++ ) { result += i; } return result; } \end{lstlisting}

    Which solves this summation:

    \[ \sum_{i=1}^n {i} \]

    But some types of problems lend themselves better to a recursive solution. To be fair, though, many problems are better solved iteratively. So how do we know which method is better?

    1. Recursion basics

      When defining a problem recursively in programming, we need two things:

      1. A terminating case: A case that ends our recursing. Often, this is some known data, something hard-coded. For example with our summation, the terminating case would be that \[ \sum_{i=1}^1 {i} = 1 \] or for a factorial, \(1! = 1\) and \(0! = 1\).
      2. A recursive case: A recursive case is what happens otherwise - if we're not to a solution yet (via the terminating case), we call the same function again, but with updated arguments. For example:
        • Factorial( 4 ) = 4 * Factorial( 3 )
        • Factorial( 3 ) = 3 * Factorial( 2 )
        • Factorial( 2 ) = 2 * Factorial( 1 )
        • Factorial( 1 ) = 1

      We can solve these basic math operations both iteratively and recursively:

      \begin{lstlisting}[style=cpp] // Iterative solution int FactorialI( int n ) { int result = 1; for ( int i = 1; i <= n; i++ ) { result *= i; } return result; } \end{lstlisting}
      \begin{lstlisting}[style=cpp] // Recursive solution int FactorialR( int n ) { if ( n == 1 || n == 0 ) { return 1; } return n * FactorialR( n-1 ); } \end{lstlisting}


    2. Breaking down problems into recursive solutions


      One of the most challenging parts of recursion, at least for me, is trying to break away from thinking of something in terms of "looping" and figuring out how to think of it "recursively". It's not as natural-feeling, so don't worry if it's confusing at first.

      Let's tackle some basic design problems to practice.

      Try to convert the Summation function to be recursive. Think about what the terminating case would be and the recursive case. Use the Factorial function for reference.
      \begin{lstlisting}[style=cpp] int SumI( int n ) { int result = 0; for ( int i = 1; i <= n; i++ ) { result += i; } return result; } \end{lstlisting}
      \begin{lstlisting}[style=cpp] int SumR( int n ) { // Terminating case? // Recursive case? } \end{lstlisting}
      Solution for recursive summation:
      \begin{lstlisting}[style=cpp] int SumR( int n ) { if ( n == 1 ) { return 1; } // Terminating case return n + SumR( n-1 ); // Recursive case } \end{lstlisting}

      Draw a line:
      Now let's make a function that will draw a line of symbols, with a parameter being the length. Iteratively, it could look like this:
      \begin{lstlisting}[style=cpp] void DrawLineI( int amount ) { for ( int i = 0; i < amount; i++ ) { cout << "-"; } } \end{lstlisting}

      How would we repeat this behavior recursively? How do we have a "count up" sort of functionality? What would be the terminating case?

      We're going to think of it a little differently: The recursive function will only output one "-" before it recurses. Each time it recurses, it draws one more dash…

      \begin{lstlisting}[style=cpp] void DrawLine_Recursive( int amount ) { cout << "-"; // Recursive case DrawLineR( amount ); } \end{lstlisting}

      However, we don't have a terminating case… it will continue looping, but it won't go forever like a bad while loop. We will eventually run out of stack space and the program will encounter a stack overflow and end.

      So what would the terminating case be? How do we adjust the amount each time? Since amount is the one parameter we have, let's have the recursion stop once it is 0. Each time we recurse, we can pass in amount-1 to the next call…

      \begin{lstlisting}[style=cpp] void DrawLine_Recursive( int amount ) { cout << "-"; // Terminating case if ( amount == 0 ) { return; } // Recursive case DrawLineR( amount - 1 ); } \end{lstlisting}


      Counting Up:
      How can we write a function that takes a start and end integer, and outputs each number between them (including the start and end)?

      Iteratively, it could look like this:

      \begin{lstlisting}[style=cpp] void CountUpI( int start, int end ) { for ( int i = start; i <= end; i++ ) { cout << i << "\t"; } } \end{lstlisting}

      Try to fill in this function to build a recursive solution:

      \begin{lstlisting}[style=cpp] void CountUpR( int start, int end ) { } \end{lstlisting}
      Solution for recursive count up:
      \begin{lstlisting}[style=cpp] void CountUpR( int start, int end ) { cout << start << "\t"; // Terminating case if ( start == end ) { return; } // recursive case CountUp_Recursive( start+1, end ); } \end{lstlisting}

    3. A case for recursion

      Although there are a lot of problems we could convert from an iterative solution to a recursive solution, there are some types of problems that really are better suited to recursion.

      1. Searching a File System


        On a harddrive, we generally have files and folders. Folders can contain files, but they will also contain subfolders as well. And subfolders can each contain their own subfolders.

        When you don't know the exact layout of the filesystem, how would you even begin to iteratively search for a specific file?

        Instead, it is good to think of it recursively. For example, say we're searching for a folder where you store your Recursion homework. We will begin searching at the top-most folder of the computer. The algorithm would then run like…

        Let's say we have a recursive function, Find( FOLDERNAME, currentFolder ).

        For this functionality, terminating cases would be:

        1. Have we found the item? Return it.
        2. Are we out of places to search? Return nothing.

        And the recursive case would be:

        1. Has a subfolder? Call Find() on that folder.


        Example filesystem:

        ├── games
        │   └── DOOM
        ├── school
        │   ├── cs210
        │   └── cs235
        │       └── recursion
        └── work
            └── TPSreports

        So steps to locate the "Recursion" folder would look like this:

        Find( "recursion", "C:" )
        Does "C:" have the recursion folder? NO...
        Does it have subfolders? YES... OK, Recurse.
        |  Find( "recursion", "C:\games" )
        |  Does "C:\games" have the recursion folder? NO...
        |  Does it have subfolders? YES... OK, Recurse.
        |  |
        |  |  Find( "recursion", "C:\games\DOOM" )
        |  |  Does "C:\games\DOOM" have the recursion folder? NO...
        |  |  Does it have subfolders? NO... Return.
        |  |
        |  Does "C:\games" have any more subfolders? NO... Return.
        Does "C:" have any more subfolders? YES... OK, Recurse.
        |  Find( "recursion", "C:\school" )
        |  Does "C:\school" have the recursion folder? NO...
        |  Does it have subfolders? YES... OK, Recurse.
        |  |
        |  |  Find( "recursion", "C:\school\cs210" )
        |  |  Does "C:\school\cs210" have the recursion folder?
        |  |  NO... Does it have subfolders? NO... Return.
        |  |
        |  Does "C:\school" have any more subfolders? YES... OK, Recurse.
        |  |
        |  |  Find( "recursion", "C:\school\cs235" )
        |  |  Does "C:\school\cs235" have the recursion folder? *YES*...
        |  |  OK, return this path.
        |  |
        |  "C:\school\cs235" path was returned, continue returning it.
        "C:\school\cs235" path was returned, continue returning it.

        And the result for finding the recursion folder is "C:\school\cs235".

      2. Solving a maze


        Solving a maze can be approached from a recursive standpoint much easier than an iterative one.

        Terminating cases:

        1. If we get to the end of the maze, SUCCESS.
        2. If we hit a dead-end, GO BACK (return).

        Recursive case: Explore each available direction, except the direction you came from.

        1. Try to go NORTH
        2. Try to go EAST
        3. Try to go SOUTH
        4. Try to go WEST


        Example step-through, going from A to B (@) is current location.

          ########   Path so far:
          ### ## #   Recursive case: Can't go NORTH, can go EAST...
        A @   ##  Z
          ###    #
          ########   Path so far: E
          ### ## #   Recursive case: Can't go NORTH, can go EAST...
        A  @  ##  Z
          ###    #
          ########   Path so far: E E
          ### ## #   Recursive case: Can't go NORTH, can go EAST...
        A   @ ##  Z
          ###    #
          ########   Path so far: E E E
          ### ## #   Recursive case: Can go NORTH...
        A    @##  Z
          ###    #
          ########   Path so far: E E E N
          ###@## #   Recursive case: Can't go NORTH, can't go EAST,
        A     ##  Z  can't go WEST...
          ###    #   Return to previous location...
          ########   Path so far: E E E
          ### ## #   Recursive case: Already went NORTH.
        A    @##  Z  Can't go EAST... Can go SOUTH...
          ###    #
          ########   Path so far: E E E S
          ### ## #   Recursive case: Can go EAST...
        A     ##  Z
          ###@   #
          ########   Path so far: E E E S E
          ### ## #   Recursive case: Can go EAST...
        A     ##  Z
          ### @  #
          ########   Path so far: E E E S E E
          ### ## #   Recursive case: Can go EAST...
        A     ##  Z
          ###  @ #
          ########   Path so far: E E E S E E E
          ### ## #   Recursive case: Can go NORTH...
        A     ##  Z
          ###   @#
          ########   Path so far: E E E S E E E N
          ### ## #   Recursive case: Can go NORTH...
        A     ##@ Z
          ###    #
          ########   Path so far: E E E S E E E N N
          ### ##@#   Recursive case: Can't go NORTH, can't go EAST,
        A     ##  Z  can't go WEST.
          ###    #   Return to previous location...
          ########   Path so far: E E E S E E E N
          ### ## #   Recursive case: Can go EAST...
        A     ##@ Z
          ###    #
          ########   Path so far: E E E S E E E N E
          ### ## #   Made it to the end!
        A     ## @Z  Return "EEESEEENE" as the solution!
          ###    #


    4.18. End of the semester


    Let me know if you have any additional suggestions! :)

    4.18.1. Ways to practice


    4.18.2. Articles to read

    4.18.3. Podcasts to listen to


    4.18.4. Books to read

    Software development:

    Bias and equity in tech:

    The Enshittification of tech:


    5. Nonogram puzzles

    How to play: Each cell in the grid of squares can either have a X (or blank) or be filled in. The filled in boxes create the pixels of an image. Each row and each column have one or more numbers. This specifies how many pixels are in that row/column. The number given is how many unbroken pixels will show up together. Two numbers separated by a space, e.g., "1 1", will have at least one empty spot between them.

    5.1. Puzzle A

    5.1.1. Hint: Among Us


    5.1.2. Hint: Star


    5.2. Puzzle B

    5.2.1. Hint: Happy


    5.2.2. Hint: Cat


    5.3. Puzzle C

    5.3.1. Hint: Love


    5.3.2. Hint: :P


    5.4. Puzzle D

    5.4.1. Hint: Tree


    5.4.2. Hint: Chocolate chip cookie



    5.5. Puzzle E

    5.5.1. Hint: Burger



    5.6. Puzzle F

    5.6.1. Hint: Bunny


    Author: Rachel Wil Sha Singh

    Created: 2024-06-04 Tue 16:39