Skip to content

Module 00 Solutions

Download Module 00 Solutions

A simple program to convert input to uppercase.

megaphone.cpp
#include <iostream>
#include <cctype>
int main(int argc, char **argv)
{
// No arguments: print feedback noise
if (argc == 1)
{
std::cout << "* LOUD AND UNBEARABLE FEEDBACK NOISE *" << std::endl;
return 0;
}
// Convert each argument to uppercase
for (int i = 1; i < argc; i++)
{
for (int j = 0; argv[i][j]; j++)
{
std::cout << (char)toupper(argv[i][j]);
}
}
std::cout << std::endl;
return 0;
}

Key Points:

  • Use std::cout instead of printf
  • toupper() returns int, cast to char
  • No spaces between arguments
  • Handle the no-argument case

A simple phonebook with ADD, SEARCH, and EXIT commands.

Contact.hpp
#ifndef CONTACT_HPP
#define CONTACT_HPP
#include <string>
class Contact {
private:
std::string _firstName;
std::string _lastName;
std::string _nickname;
std::string _phoneNumber;
std::string _darkestSecret;
bool _isEmpty;
public:
Contact();
~Contact();
void setFirstName(const std::string& firstName);
void setLastName(const std::string& lastName);
void setNickname(const std::string& nickname);
void setPhoneNumber(const std::string& phoneNumber);
void setDarkestSecret(const std::string& secret);
void setIsEmpty(bool isEmpty);
std::string getFirstName() const;
std::string getLastName() const;
std::string getNickname() const;
std::string getPhoneNumber() const;
std::string getDarkestSecret() const;
bool isEmpty() const;
};
#endif
PhoneBook.hpp
#ifndef PHONEBOOK_HPP
#define PHONEBOOK_HPP
#include "Contact.hpp"
#include <string>
class PhoneBook {
private:
Contact _contacts[8];
int _currentIndex;
int _totalContacts;
std::string _truncate(const std::string& str) const;
void _displayContactRow(int index) const;
std::string _getInput(const std::string& prompt) const;
public:
PhoneBook();
~PhoneBook();
void addContact();
void searchContacts() const;
};
#endif
Contact.cpp
#include "Contact.hpp"
Contact::Contact() : _isEmpty(true) {}
Contact::~Contact() {}
void Contact::setFirstName(const std::string& firstName) {
_firstName = firstName;
}
void Contact::setLastName(const std::string& lastName) {
_lastName = lastName;
}
void Contact::setNickname(const std::string& nickname) {
_nickname = nickname;
}
void Contact::setPhoneNumber(const std::string& phoneNumber) {
_phoneNumber = phoneNumber;
}
void Contact::setDarkestSecret(const std::string& secret) {
_darkestSecret = secret;
}
void Contact::setIsEmpty(bool isEmpty) {
_isEmpty = isEmpty;
}
std::string Contact::getFirstName() const { return _firstName; }
std::string Contact::getLastName() const { return _lastName; }
std::string Contact::getNickname() const { return _nickname; }
std::string Contact::getPhoneNumber() const { return _phoneNumber; }
std::string Contact::getDarkestSecret() const { return _darkestSecret; }
bool Contact::isEmpty() const { return _isEmpty; }
PhoneBook.cpp
#include "PhoneBook.hpp"
#include <iostream>
#include <iomanip>
#include <cstdlib>
PhoneBook::PhoneBook() : _currentIndex(0), _totalContacts(0) {}
PhoneBook::~PhoneBook() {}
std::string PhoneBook::_truncate(const std::string& str) const {
if (str.length() > 10)
return str.substr(0, 9) + ".";
return str;
}
void PhoneBook::_displayContactRow(int index) const {
std::cout << std::setw(10) << std::right << index << "|";
std::cout << std::setw(10) << std::right << _truncate(_contacts[index].getFirstName()) << "|";
std::cout << std::setw(10) << std::right << _truncate(_contacts[index].getLastName()) << "|";
std::cout << std::setw(10) << std::right << _truncate(_contacts[index].getNickname()) << std::endl;
}
std::string PhoneBook::_getInput(const std::string& prompt) const {
std::string input;
while (true) {
std::cout << prompt;
if (!std::getline(std::cin, input)) {
std::cout << std::endl;
std::exit(0);
}
if (!input.empty())
break;
std::cout << "Field cannot be empty. Please try again." << std::endl;
}
return input;
}
void PhoneBook::addContact() {
Contact newContact;
newContact.setFirstName(_getInput("Enter first name: "));
newContact.setLastName(_getInput("Enter last name: "));
newContact.setNickname(_getInput("Enter nickname: "));
newContact.setPhoneNumber(_getInput("Enter phone number: "));
newContact.setDarkestSecret(_getInput("Enter darkest secret: "));
newContact.setIsEmpty(false);
_contacts[_currentIndex] = newContact;
_currentIndex = (_currentIndex + 1) % 8; // Circular buffer
if (_totalContacts < 8)
_totalContacts++;
std::cout << "Contact added successfully!" << std::endl;
}
void PhoneBook::searchContacts() const {
if (_totalContacts == 0) {
std::cout << "PhoneBook is empty." << std::endl;
return;
}
// Display header
std::cout << std::setw(10) << "Index" << "|";
std::cout << std::setw(10) << "First Name" << "|";
std::cout << std::setw(10) << "Last Name" << "|";
std::cout << std::setw(10) << "Nickname" << std::endl;
std::cout << std::string(44, '-') << std::endl;
// Display all contacts
for (int i = 0; i < _totalContacts; i++)
_displayContactRow(i);
// Get index from user
std::cout << "Enter index to view details: ";
std::string indexStr;
if (!std::getline(std::cin, indexStr)) {
std::cout << std::endl;
return;
}
// Validate index
if (indexStr.length() != 1 || indexStr[0] < '0' || indexStr[0] > '7') {
std::cout << "Invalid index." << std::endl;
return;
}
int index = indexStr[0] - '0';
if (index >= _totalContacts) {
std::cout << "Invalid index." << std::endl;
return;
}
// Display full contact details
std::cout << "First Name: " << _contacts[index].getFirstName() << std::endl;
std::cout << "Last Name: " << _contacts[index].getLastName() << std::endl;
std::cout << "Nickname: " << _contacts[index].getNickname() << std::endl;
std::cout << "Phone Number: " << _contacts[index].getPhoneNumber() << std::endl;
std::cout << "Darkest Secret: " << _contacts[index].getDarkestSecret() << std::endl;
}

Key Points:

  • Fixed array of 8 contacts (no dynamic allocation)
  • Circular buffer: oldest contact replaced when full
  • All attributes private with getters/setters
  • Truncate strings > 10 chars with .
  • Use std::setw(10) and std::right for formatting
  • Handle EOF (Ctrl+D) gracefully
  • Reject empty fields

Reconstruct Account.cpp from the provided Account.hpp and log file. Static members track global state across all accounts.

Account.cpp
#include "Account.hpp"
#include <iostream>
#include <iomanip>
#include <ctime>
// Initialize static members
int Account::_nbAccounts = 0;
int Account::_totalAmount = 0;
int Account::_totalNbDeposits = 0;
int Account::_totalNbWithdrawals = 0;
// Static getters
int Account::getNbAccounts() { return _nbAccounts; }
int Account::getTotalAmount() { return _totalAmount; }
int Account::getNbDeposits() { return _totalNbDeposits; }
int Account::getNbWithdrawals() { return _totalNbWithdrawals; }
// Display timestamp: [YYYYMMDD_HHMMSS]
void Account::_displayTimestamp() {
std::time_t now = std::time(NULL);
std::tm* local = std::localtime(&now);
std::cout << "["
<< (local->tm_year + 1900)
<< std::setfill('0') << std::setw(2) << (local->tm_mon + 1)
<< std::setfill('0') << std::setw(2) << local->tm_mday
<< "_"
<< std::setfill('0') << std::setw(2) << local->tm_hour
<< std::setfill('0') << std::setw(2) << local->tm_min
<< std::setfill('0') << std::setw(2) << local->tm_sec
<< "] ";
}
// Display all accounts info
void Account::displayAccountsInfos() {
_displayTimestamp();
std::cout << "accounts:" << _nbAccounts
<< ";total:" << _totalAmount
<< ";deposits:" << _totalNbDeposits
<< ";withdrawals:" << _totalNbWithdrawals << std::endl;
}
// Constructor with initial deposit
Account::Account(int initial_deposit)
: _accountIndex(_nbAccounts),
_amount(initial_deposit),
_nbDeposits(0),
_nbWithdrawals(0) {
_nbAccounts++;
_totalAmount += initial_deposit;
_displayTimestamp();
std::cout << "index:" << _accountIndex
<< ";amount:" << _amount
<< ";created" << std::endl;
}
// Destructor
Account::~Account() {
_displayTimestamp();
std::cout << "index:" << _accountIndex
<< ";amount:" << _amount
<< ";closed" << std::endl;
}
// Make a deposit
void Account::makeDeposit(int deposit) {
_displayTimestamp();
std::cout << "index:" << _accountIndex
<< ";p_amount:" << _amount
<< ";deposit:" << deposit;
_amount += deposit;
_nbDeposits++;
_totalAmount += deposit;
_totalNbDeposits++;
std::cout << ";amount:" << _amount
<< ";nb_deposits:" << _nbDeposits << std::endl;
}
// Make a withdrawal (returns false if insufficient funds)
bool Account::makeWithdrawal(int withdrawal) {
_displayTimestamp();
std::cout << "index:" << _accountIndex
<< ";p_amount:" << _amount
<< ";withdrawal:";
if (withdrawal > _amount) {
std::cout << "refused" << std::endl;
return false;
}
_amount -= withdrawal;
_nbWithdrawals++;
_totalAmount -= withdrawal;
_totalNbWithdrawals++;
std::cout << withdrawal
<< ";amount:" << _amount
<< ";nb_withdrawals:" << _nbWithdrawals << std::endl;
return true;
}
// Check current amount
int Account::checkAmount() const {
return _amount;
}
// Display individual account status
void Account::displayStatus() const {
_displayTimestamp();
std::cout << "index:" << _accountIndex
<< ";amount:" << _amount
<< ";deposits:" << _nbDeposits
<< ";withdrawals:" << _nbWithdrawals << std::endl;
}

Key Points:

  • Static members must be initialized outside the class (in .cpp file)
  • _displayTimestamp() uses <ctime> functions: time(), localtime()
  • Use std::setfill('0') and std::setw(2) for zero-padded numbers
  • Constructor increments _nbAccounts and adds to _totalAmount
  • makeWithdrawal() returns false and prints “refused” if insufficient funds
  • Output format must match the log file exactly (semicolon-separated key:value pairs)