Guidance

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++;
        }
    }*/

    }
}
I guess the first thing you need is a constructor to initialise all your members.

> Measure m(1,3);
Like say
Measure m(1,3,"tsp");
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 believe you need measure to have a ctor that sets up 'unit' and the fraction.

Also, the overloaded *= operator function has a red line under the multiplication part '*' that says no operator matches these operands.

yes, *= says provide measure*fraction, which makes no sense to the compiler. You need to define the * operator for these types first. Or you could inherit into instead of has-a.


Also, I am not sure where to put unitStrings[], and conversionTable[]?
these seem like they should be global scope constants in a namespace to me, so you can use them outside these objects as needed. If you never need that you can put them inside. Generally, I put constant data at the scope that everything that needs them can have them. Static in the class lets you access them anywhere so long as you have that class, but it you had something else that had the same data without the conversion class needed you would have to pull in more than you needed in your new program. Its not a big deal for this project, just explaining how to think about it a bit.
Last edited on
I appreciate your guys input. I was able to work on phase one some and now I have to move on for next weeks assignment. This assignment was over my head for the most part. It was very discouraging to be given a project with no instructions from the teacher on how to go about it.
Topic archived. No new replies allowed.