date::prev with no explicit arguments

Won’t compile

  1. kheslin2/prev.C. Missing semicolon in one-argument date::next.
  2. jcrews1/prev.C. Need {curly braces} around initial values of array elements.

Bugs in the logic

  1. jcrews1/prev.C. date::prev changes March 1, 2025 to March 2, 2025.
  2. kheslin2/prev.C. date::prev changes March 1, 2025 to March 0, 2025.
  3. llawrence18/prev.C. date::prev changes January 1, 2025 to December 1, 2024.

Unnecessary duplication

  1. fkhan67prev.C, gm9/prev.C, jr224/prev.C. Need to write
    day = date_length[month];
    only once, if you write it in the right place.
    void date::prev()
    {
    	if (day > 1) {
    		--day;
    	} else {
    		if (month > 1) {
    			--month;
    		} else {
    			month = 12;
    			--year;
    		}
    		day = date_length[month];
    	}
    }
    
    fkhan67/interesting.C. In the member function Timer::tick, need to write
    seconds = 59;
    only once if you write it i the right place.
    When the Timer is already at 00:00:00, Timer::tick changes it to 00:59:59.
    void Timer::tick()
    {
    	if (finished()) {
    		return;   //Clean: do nothing if timer is already at 00:00:00.
    	}
    
    	if (seconds > 0) {
    		--seconds;
    	} else {
                    seconds = 59;
    		if (minutes > 0) {
    			--minutes;
    		} else {
    			minutes = 59;
    			--hours;  //Arrive here only if hours > 0
    		}
    	}
    }
    

The setfill i/o manipulator

fkhan67/interesting.C outputs each integer as a two-digit number, even if it is a single digit: 00:03:05

	void display() const {
		cout << (hours   < 10 ? "0" : "") << hours   << ":"
		     << (minutes < 10 ? "0" : "") << minutes << ":"
		     << (seconds < 10 ? "0" : "") << seconds << endl;
	}
#include <iomanip>  //for the i/o manipulatots setw and setfill
using namespace std;

Timer::void display() const
{
	cout << setfill('0')
	     << setw(2) << hours   << ":"
	     << setw(2) << minutes << ":"
	     << setw(2) << seconds << "\n";
}

A friend function of a class

In gm9/interesting.C, the following member function uses two objects of class character.

  1. The character object that the member function belongs to. (We use the name and attack data members of this object.)
  2. The character object that is passed as a reference named defender.
//Makes another character type for battle purposes using "&" to get the address
void attackEnemy(character &defender) {
	int damage = (attack - defender.defense /2) + (rand() % 50);	//Random extra damage for variety
	if (damage < 0) damage = 0;					//Makes no negative damage
	defender.health -= damage;
	if (defender.health < 0) defender.health = 0;			//Makes no negative health

	cout << name << " attacks " << defender.name << " for " << damage << " damage!\n";
	cout << defender.name << " now has " << defender.health << " health left.\n";
	}

Member function vs. friend vs. neither:

  1. If a function uses the private members of one object, make the function a member function of the object.
  2. If a function uses the private members of two objects of the same class, make the function a friend function of the class, rather than a member function. This lets you give visible names (attacker and defender, below) to both of the objects, making the code easier to read.
  3. If a function does not use the privat members of any object, make the function a plain old function, neither a member function nor a freind.
class character {
	//Declarations for data members and member functions

	//Declaration for a friend function
	friend void attackEnemy(const character& attacker, character& defender);
};

//This function can change the defender object, but not the attacker object.

void attackEnemy(const character& attacker, character& defender)
{
	//Random extra damage for variety
	int damage {attacker.attack - defender.defense/2 + rand() % 50};
	if (damage < 0) {          //Damage can't be negative.
		damage = 0;
	}

	defender.health -= damage;
	if (defender.health < 0) {  //Health can't be negative.
		defender.health = 0;
	}

	cout << attacker.name << " attacks " << defender.name << " for " << damage << " damage!\n";
	cout << defender.name << " now has " << defender.health << " health left.\n";
}

Use a std::list, not a std::vector, when removing items deep in the middle

In ak205/interesting.C,

#include <list>
using namespace std;

class Library {
	//Declaration for a data member
	list<string> books;
};

void Library::removeBook(string book)
{
	const list<string>::size_type n {books.size();}
	books.remove(book);   //no return value

	if (books.size() == n - 1) {
                cout << "Book '" << book << "' removed successfully!\n";
	} else {
		cerr << "Book '" << book << "' not found in the library.\n";
	}
}