Mini Project 1 — Temperature Converter¶
Difficulty: Beginner · Estimated effort: 2–3 hours ·
Prerequisites: Module 2 — Classes and Objects,
Module 4 — Encapsulation ·
Combines: a class, constructors, const member functions, an invariant
No complete solution is provided. The brief is the specification; the checklist at the end is how you review your own work.
1. Scenario¶
A science teacher keeps a paper log of readings taken in different units: Celsius from the classroom thermometer, Fahrenheit from an old wall gauge, Kelvin from a sensor readout. Every calculation on that log is done by hand, and two of the last three mistakes were unit conversions rather than arithmetic.
You are asked for a small program that stores a reading as a thing — a temperature — rather
than as a bare double, so that the unit cannot be forgotten.
2. Problem statement¶
Build a Temperature type that owns a value and the scale it was measured on, can report the
same reading in any of Celsius, Fahrenheit and Kelvin, compares correctly across scales, and
refuses to represent a temperature below absolute zero.
The invariant is the interesting part: -300 C is not an unreachable state, it is not a
temperature at all, and the type must say so at the moment of construction rather than at the
moment of use.
3. User requirements¶
- [ ] Enter a reading and say which scale it is in.
- [ ] Ask for any reading in any of the three scales.
- [ ] See it printed readably, with the scale named.
- [ ] Compare two readings that were given in different scales and get the truth.
- [ ] Be told clearly when a value is impossible, rather than getting a wrong number.
4. Functional requirements¶
- [ ] Construct from a value and a scale.
- [ ] Convert to any of
Celsius,Fahrenheit,Kelvin. - [ ] Print with a fixed number of decimal places and the scale name.
- [ ]
operator==andoperator<that are correct across scales. - [ ] Construction below absolute zero is rejected with a message naming the value and the lowest representable one.
- [ ] A way to ask for the canonical (Kelvin) value, so other code never guesses.
5. Non-functional requirements¶
- [ ] One header and one source file, plus
main.cpp; no globals. - [ ] Builds with
g++ -std=c++17 -Wall -Wextra -Werrorwith no warnings. - [ ] ASCII-only output.
- [ ] Conversion constants appear in exactly one place in the code.
- [ ] Every member function that does not change the object is
const. - [ ] No floating-point equality against a literal in tests — compare with a tolerance.
6. Suggested features¶
Pick the ones that interest you; none is required.
- Parse a reading from a string such as
21.5 C. - Sort a
std::vector<Temperature>and print the range. describe()returning a phrase such as21.5 C (294.7 K).- A
Temperature::zero()factory for absolute zero.
7. OOP concepts involved¶
| Concept | Where it appears |
|---|---|
| Encapsulation | The value is private and can never be below absolute zero |
| Constructors | The rejection rule lives in the constructor, so no invalid object exists |
const correctness |
Conversions and comparisons do not modify the reading |
| Operator overloading | ==, <, << make the type usable like a number |
| Static constants | Conversion factors are class-level, not file-level globals |
| Composition | A Log holding std::vector<Temperature> if you do the sorting feature |
8. Suggested design considerations¶
Decide where the value lives. Two designs are defensible: store the value in the scale it was given, or normalise to Kelvin on construction and store that. Normalising makes comparison trivial and conversion cheap; storing as given preserves what the user typed, which matters if the display must round-trip. Choose one, and write down the choice.
One conversion funnel. Every conversion should go through a single canonical form. A matrix of six direct formulas will have one of them wrong, and you will not find it by reading.
Round on output, never on storage. Storing a rounded value makes repeated conversions drift, and the drift is invisible until it is embarrassing.
Absolute zero is different per scale. Kelvin's floor is 0; Celsius' is -273.15. Decide
whether the check happens in the constructor for the given scale or after normalising, and say
why in a comment.
9. Minimum viable version¶
A Temperature class with private members, a constructor that validates, toCelsius(),
toFahrenheit() and toKelvin(), and a print()/operator<<. A main that converts a few
readings and prints them, plus one rejected construction.
10. Intermediate extension¶
Add comparison operators and a main that reads a handful of readings, sorts them and prints
the coldest and warmest. Then break it deliberately: construct a Temperature at
-273.15 C and at -273.16 C and confirm the boundary behaves as you documented.
11. Advanced extension¶
Introduce a fourth scale (Rankine) without editing the conversion formulas — for example a
small Scale record holding the offsets to Kelvin, registered in one place. Then state in
writing what the change cost you: files touched, lines changed, and whether the design made it
easy or merely possible.
12. Testing checklist¶
- [ ]
0 Cis32 Fis273.15 K, to your tolerance - [ ]
100 Cis212 F - [ ]
-40 Cequals-40 F - [ ] Absolute zero is accepted; one hundredth of a degree below it is rejected
- [ ] Comparing
0 Cwith32 Freports equal - [ ] Sorting a mixed-scale vector orders by real temperature, not by raw number
- [ ] The printed form names the scale
- [ ] Constructing the lowest valid value prints without special-casing
13. Documentation checklist¶
- [ ] A header comment saying what the type represents and what its invariant is
- [ ] A comment naming the canonical form and why
- [ ] A short
READMEor block comment showing example input and output - [ ] The rule for impossible values written where a user of the class will read it
- [ ] A note on the tolerance used in comparisons
14. Self-evaluation rubric¶
| Criterion | Excellent looks like | Weight |
|---|---|---|
| Correctness | All three scales round-trip; the boundary is exact | 30% |
| Encapsulation | No invalid Temperature can exist; no public data members |
25% |
| Interface | Small, const-correct, and usable without reading the implementation |
15% |
| Error reporting | The refusal names the value and the limit | 10% |
| Code quality | Conversion constants in one place; no warnings; clear names | 10% |
| Documentation | Invariant and canonical form written down | 10% |
Related: Mini projects · Project roadmap · All projects · Module 4 — Encapsulation