Skip to content

Teaching Notes: Module 00

This is the student’s first exposure to C++. The goal is NOT to give answers, but to guide them toward understanding. Ask leading questions, let them struggle a bit, then help them connect the dots.


  • Basic I/O with std::cout
  • Command-line arguments (argc, argv)
  • String manipulation (uppercase conversion)
  • Loop iteration over strings
  1. Using printf

    • Student habit from C. Gently remind: “What’s the C++ way to output?”
  2. Using toupper() incorrectly

    // WRONG - toupper returns int
    str[i] = toupper(str[i]); // Works but implicit conversion
    // BETTER - explicit cast
    str[i] = static_cast<char>(toupper(str[i]));
  3. Forgetting the no-argument case

    • Subject says: print * LOUD AND UNBEARABLE FEEDBACK NOISE *
  4. Not handling spaces between arguments

    • ./megaphone "Hello" "World" should print HELLOWORLD (no space)
    • But ./megaphone "Hello World" should print HELLO WORLD
  1. “How do you access command-line arguments in C++?”
  2. “What’s different about std::cout compared to printf?”
  3. “How can you convert a character to uppercase?”
  4. “What happens when no arguments are provided?”
  • Using printf, scanf, or any C I/O
  • Complex code for a simple task (overengineering)

  • Class design (two classes: PhoneBook, Contact)
  • Encapsulation (private attributes, public methods)
  • Arrays (fixed size, no dynamic allocation)
  • Input validation
  • Output formatting with iomanip
  • Object lifecycle
  • Max 8 contacts - oldest replaced when full
  • No dynamic allocation - fixed array, not pointers
  • Fields: first name, last name, nickname, phone number, darkest secret
  • No empty fields - must validate input
  • Display format: 10-char columns, right-aligned, truncate with ’.’
  • Commands: ADD, SEARCH, EXIT only
  1. Using vectors/dynamic allocation

    • Subject explicitly forbids dynamic allocation
    • Must use: Contact _contacts[8];
  2. Wrong display format

    // WRONG
    std::cout << name << std::endl;
    // RIGHT
    std::cout << std::setw(10);
    if (name.length() > 10)
    std::cout << name.substr(0, 9) + ".";
    else
    std::cout << name;
  3. Not tracking the oldest contact

    • Need an index to know which contact to replace
  4. Empty field acceptance

    // Need to reject empty input
    while (input.empty()) {
    std::cout << "Field cannot be empty: ";
    std::getline(std::cin, input);
    }
  5. Not handling EOF (Ctrl+D)

    • std::getline returns false on EOF
    • Program should exit gracefully
  6. Making attributes public

    • Everything that can be private SHOULD be private
PhoneBook
├── Private:
│ ├── Contact _contacts[8]
│ ├── int _count (or _index, _oldest)
│ └── (helper methods)
├── Public:
│ ├── PhoneBook() - constructor
│ ├── void addContact(Contact c)
│ ├── void search()
│ └── Contact getContact(int index)
Contact
├── Private:
│ ├── std::string _firstName
│ ├── std::string _lastName
│ ├── std::string _nickname
│ ├── std::string _phoneNumber
│ └── std::string _darkestSecret
├── Public:
│ ├── Contact() - constructor
│ ├── Setters for each field
│ ├── Getters for each field
│ └── bool isEmpty() - check if contact is set
  1. “What data does a Contact need to store?”
  2. “How will PhoneBook know when it’s full?”
  3. “Which contact should be replaced when the phonebook is full?”
  4. “How do you truncate a string that’s too long?”
  5. “What’s the difference between public and private?”
  6. “Why would you want to make attributes private?”
  • All attributes public
  • Using vectors, lists, or dynamic memory
  • Hardcoded magic numbers (use constants)
  • No input validation
  • Crashes on edge cases (empty input, EOF, invalid index)

  • Reading existing code and matching behavior
  • Static members and methods
  • Understanding log output
  • Reverse-engineering from header + tests

Student must:

  1. Read Account.hpp to understand the interface
  2. Run tests.cpp (it won’t compile yet)
  3. Look at the log file to understand expected output
  4. Implement Account.cpp to match the log (except timestamps)
  1. Not studying the log file carefully

    • The log shows exact output format
    • Order of destructor calls matters
  2. Static member initialization

    // In Account.cpp (NOT in header!)
    int Account::_nbAccounts = 0;
    int Account::_totalAmount = 0;
    int Account::_totalNbDeposits = 0;
    int Account::_totalNbWithdrawals = 0;
  3. Timestamp format

    • [YYYYMMDD_HHMMSS]
    • Use <ctime> for time functions
  4. Destructor order

    • Objects destroyed in reverse order of creation
    • Array elements: last created = first destroyed
  1. “What’s the difference between static and non-static members?”
  2. “Where should static members be initialized?”
  3. “Why does the log show accounts being destroyed in reverse order?”
  4. “How can you format time in C++?”

  1. Mindset shift: “Objects have behavior, not just data”
  2. Memory safety: “std::string manages memory for you”
  3. Type safety: “Let the compiler help you catch mistakes”
  1. Why classes over structs?

    • Encapsulation: hide internal details
    • Behavior: methods operate on data
    • Lifecycle: constructors/destructors
  2. Why private attributes?

    • Control: you decide how data is accessed/modified
    • Validation: setters can check input
    • Future-proofing: internal representation can change
  3. Why std::string over char*?

    • No manual memory management
    • No buffer overflows
    • Convenient operations (concatenation, comparison)

Instead of saying: “Use std::setw(10) for formatting”

Say: “Take a look at <iomanip>. There’s a function that sets field width. What does it do when the text is shorter than the width?”

Instead of saying: “You need to track the index of the oldest contact”

Say: “When the phonebook is full and you add a new contact, how will you know which one to replace? What information do you need to track?”

  • No forbidden functions (printf, malloc, etc.)
  • No using namespace std;
  • Include guards present
  • Implementation not in headers
  • Output ends with newline
  • Classes properly encapsulated
  • Memory properly managed (no leaks)
  • Edge cases handled
  • Code is readable and makes sense