Skip to content

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== and operator< 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 -Werror with 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 as 21.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 C is 32 F is 273.15 K, to your tolerance
  • [ ] 100 C is 212 F
  • [ ] -40 C equals -40 F
  • [ ] Absolute zero is accepted; one hundredth of a degree below it is rejected
  • [ ] Comparing 0 C with 32 F reports 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 README or 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