# This Unit Is Engaged

Assigned
Due

Oct 18
80 pts
Nov 1

You are to write a program for doing unit conversion. Read the standard input. That will define the dimensions, the units used for each, and the conversion factors. It then requests conversions between quantities in differing units. The output of the program is the result of the conversion requests. For instance, this input:

dim length cm def m = 100 cm def in = 2.54 cm def ft = 12 in conv 3.5 ft to m
produces this output
3.5 ft = 1.0668 m (length)

## Input Format

The input consists of a series of statements, each being one of three types: dimension (dim), conversion factor (def), or conversion request (conv). Each statement type consists of a fixed number of items separated by spaces, as follows.

dim dimension baseunit
The dim statement specifies a dimension (such as distance, weight, time, etc.) and some unit appropriate for that dimension. Any appropriate unit may be chosen. The dimension and baseunit may each be any non-blank string. The baseunit is being defined, and must not have been defined previously.
def newunit = factor oldunit
The factor is a positive floating-point number, while newunit and oldunit are any non-blank strings which serve as unit names. The oldunit must be some unit name which has already been defined, and newunit is being defined and must not have been defined previously. The = is literal. This statement defines newunit to be equal to factor oldunits.
conv amount fromunits to tounits
The amount is any floating point number, and fromunits and tounits are non-blank unit names which have already been defined. This statement requests the program to convert the quantity of amount fromunits into some equivalent quantity expressed in tounits.

## Output

Only conv statements produce output, unless there is an error. They produce the result of the conversion request, giving the number of tounits equivalent to the given number of fromunits. The output should also specify the dimension of the given units. If the dimensions don't match (e.g., a conversion from feet to pounds is specified), output an error message instead of a conversion result.

## Procedure

Use a map to keep track of the definition of each unit. I used a map from string (the unit name) to a small class containing the dimension (a string) and a scale factor representing the conversion of the indicated unit to the base unit for the dimension. Alternatively, it would be possible to use two maps, one string to string for the dimension, and string to double for the factor. This structure is updated by dim and def statement, and used by the conv statement to compute the results.

In hopes of making this clearer, here is how the data structure changes when reading the dim and def records in the above example. The sequence below shows each of these records, and the resulting map information.

dim length cm
cm ⇒ [ 1.0, length ]
def m = 100 cm
cm ⇒ [ 1.0, length ]
m ⇒ [ 100.0, length ]
def in = 2.54 cm
cm ⇒ [ 1.0, length ]
m ⇒ [ 100.0, length ]
in ⇒ [ 2.54, length ]
def ft = 12 in
cm ⇒ [ 1.0, length ]
m ⇒ [ 100.0, length ]
in ⇒ [ 2.54, length ]
ft ⇒ [ 30.48, length ]
Each unit is stored with its dimension, and the factor needed to convert it to the base unit for its dimension. The initial dim creates an entry for unit cm with a multiplier of 1.0 and dimension of length. The 1.0 is the factor to convert from cm to cm. Each of the def statements create entries for converting to cm by multiplying the input factor times the stored factor for the pre-existing unit. For m, the new factor is 100.0×1.0=100.0, and in 2.54×1.0=2.54. For ft, it's 12.0×2.54=30.48, the new factor 12 times the existing factor of 2.54 for the existing unit in.

Once the map information is built, the conv statements can be processed by taking the input quantity times the scale for the starting unit, and dividing by the scale for ending unit. For the “conv 3.5 ft to m” in the small example file, that gives the calculation 3.5×30.48÷100=1.0668. Or, more properly, with units, 3.5ft×(30.4cm/1ft)×(1m/100cm)=1.0668m. Each conv is satisfied by converting the figure to the base unit for that dimension, then converting back to the target unit. The operation can also easily check that both the starting and ending units belong to the same dimension.

You will want to make use of functions. If you want to send a map as a parameter, you will want to pass it by reference.

You can read the entire input stream using >>. This will be easier than trying to read and parse lines of text. Especially since the input specification doesn't say anything about statements being lines.

## Error Reporting

You should detect and report each of the following errors in the input stream. For those described as format errors, your program should halt after the error is detected; for others, you should continue reading and processing input.
1. If you see anything but dim, def or conv where the first word of a statement should be. This is a format error.
2. If reading fails for any of the items that make up a statement. Format error.
3. If the = in def or the to in conv are missing. Format error.
4. If any unit name that should have already been defined isn't, or if any unit name being defined has already been defined.
5. If the factor on a def is not positive.
6. If the units on a conv do not conform (belong to different dimensions).

## What We Are Not Doing

It would be nice to handle compound units, like m/s or ft-lb. Maybe next assignment.

## Submission

When your program works, is well-commented, and nicely indented, submit over the web here.