Hi, I haven't programmed much in about a year. I have now enrolled in an online class, and there are no refreshers. Just an assignment right off the bat. Unfortunately, I have not retained as much as I would like from the past. I need some guidance in getting the big picture to the puzzle, and start piecing things together.
Some particulars I have. Should I be using the constructor from the Fraction class or should I be creating a new one for Measure class? I'll post that constructor below. Not posting all of Fraction class because it seems I am already posting too much. Also, the overloaded *= operator function has a red line under the multiplication part '*' that says no operator matches these operands. Also, I am not sure where to put unitStrings[], and conversionTable[]?
Here is the assignment. Phase 1 (out of 4) posted only:
This project will depend heavily on your Fraction and MyString classes.
The project will be written in four phases. You should test each phase carefully before moving on to the next phase.
Phase 1: The Measure Class
The Measure class consists of a Fractional amount and an associated English unit (e.g., "3/4 tsp"). A Measure object can be scaled by multiplying by another Fraction. To handle this scaling, it must include an overloaded *= operator. The Measure class is responsible for converting the amount to the most "reasonable" unit, which is the largest unit where the amount is greater than or equal to 1 if such a unit exists. Otherwise, the unit should be the smallest known unit. For example, 3 pint should be printed as 1+1/2 qt, 1/2 gal should be printed as 2 qt (not 4 pint), and 1/3 dram remains 1/3 dram.
The class will also have overloaded insertion and extraction operators.
Rather than writing a bunch of special conditionals, we will store the conversion factors in a table (array) so you can convert up and down as needed in the Measure object. Since this table is only used by the Measure class and can be shared among all Measure objects, this is a good opportunity for use of static data. By the way, the conversions are:
4/3 dram = 1 tsp
3 tsp = 1 tbsp
2 tbsp = 1 oz
8 oz = 1 cup
2 cup = 1 pint
2 pint = 1 qt
4 qt = 1 gal
2 gal = 1 peck
4 peck = 1 bushel
55/7 bushel = 1 barrel
6000 barrel = 1 acre_ft
Here is my Measure class declaration. There is some stuff going on with constants and "static" that you may not have seen before. Basically, you shouldn't simply declare a const in a class. You have to declare it as a static const. This is because you don't want a separate LARGEST_UNIT (for example) constant for each Measure object, you just want a single LARGEST_UNIT constant that any object in the Measure class can access. This is done with the static keyword. With the arrays, you then have to initialize the array OUTSIDE of the class declaration, as you can see below.
class Measure {
public:
friend ostream& operator<<(ostream& out, const Measure &printMe);
friend istream& operator>>(istream& in, Measure &readMe);
Measure operator*=(const Fraction &right);
private:
void simplify();
static const int LARGEST_UNIT = 11;
static const int SMALLEST_UNIT = 0;
// these two constants: we'll be using a system where
// dram = 0, tsp = 1, tbsp = 2, and so on. So the
// smallest unit (dram) is represented by 0, and the
// largest unit (acre_ft) is represented by 11.
static const int NUM_UNITS = 12;
static const Fraction conversionTable[NUM_UNITS];
static const MyString unitStrings[NUM_UNITS];
Fraction amount;
int unit; //if unit = 0, the unit is dram.
//if unit = 1, the unit is tsp, and so on.
};
const MyString Measure::unitStrings[] =
{"dram", "tsp", "tbsp", "oz", "cup", "pint",
"qt", "gal", "peck", "bushel", "barrel", "acre_ft"};
const Fraction Measure::conversionTable[] =
{Fraction(4,3), 3, 2, 8, 2, 2, 4, 2, 4, Fraction(55,7), 6000};
// these two const definitions should go in the implementation file,
// not in the specification file.
Here is my simplify function, complete except that 2 conditions and 2 statements have been removed. It makes sure that the units meet the requirements given in the assignment, that is, the amount should be made as small as possible but never less than 1 (unless of course the unit is already "dram". In that case, the amount will of course have to be less than 1).
void Measure::simplify()
{
// make the amount bigger if it is less than 1, unless the unit is already
//"dram" (in which case the amount can't be made any bigger).
while (<condition>) {
<statement to make the amount bigger, since we are making the unit smaller>
unit--;
}
//make the amount smaller if it can be made smaller without making it
//less than 1, unless the unit is already acre_ft (in which case the
//amount can't be made any smaller)
while (<condition>) {
<statement to make the amount smaller, since we are making the unit bigger>
unit++;
}
}
Of the three remaining functions in the Measure class (besides simplify), one of mine is 2 lines, one is 3 lines, and one is 8 lines. When counting lines I don't count declarations or blank lines. I'm telling you this not because you should try to make yours exactly like mine, but so that you won't go too far off in the wrong direction. For example if you are writing your insertion operator and you are up to 12 lines and still going strong, you know something is wrong!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// Fraction constructor
Fraction::Fraction(int inNumerator, int inDenominator)
{
assert(inDenominator != 0);
numerator = inNumerator;
denominator = inDenominator;
simplify(); // This simplify function is in Fraction. Different one in Measure
// class.
}
// main
#include <iostream>
#include "measure.h"
#include "Fraction.h"
using namespace std;
using namespace cs_measure;
int main()
{
Measure m(1,3);
return 0;
}
// measure.h
#include "Fraction.h"
#include "myString.h"
using namespace cs_fraction;
using namespace cs_mystring;
namespace cs_measure
{
class Measure {
public:
friend ostream& operator<<(ostream& out, const Measure& printMe);
friend istream& operator>>(istream& in, Measure& readMe);
Measure operator*=( const Fraction& right);
private:
void simplify();
static const int LARGEST_UNIT = 11;
static const int SMALLEST_UNIT = 0;
// these two constants: we'll be using a system where
// dram = 0, tsp = 1, tbsp = 2, and so on. So the
// smallest unit (dram) is represented by 0, and the
// largest unit (acre_ft) is represented by 11.
static const int NUM_UNITS = 12;
static const Fraction conversionTable[NUM_UNITS];
static const MyString unitStrings[NUM_UNITS];
Fraction amount;
int unit; //if unit = 0, the unit is dram.
//if unit = 1, the unit is tsp, and so on.
};
}
// measure.cpp
#include <iostream>
#include <cassert>
#include "measure.h"
#include "Fraction.h"
#include "myString.h"
using namespace std;
using namespace cs_fraction;
namespace cs_measure
{
Measure Measure::operator *= (const Fraction& right)
{
*this = *this * right;
return *this;
}
ostream& operator << (ostream& out, const Measure& printMe)
{
Measure m;
m.amount;
}
istream& operator >> (istream& in, Measure& readMe)
{
}
void Measure::simplify()
{/*
while (<condition>) {
<statement to make the amount bigger, since we are making the unit smaller>
unit--;
}
while (<condition>) {
<statement to make the amount smaller, since we are making the unit bigger>
unit++;
}
}*/
}
}
|