### Freezing and Boiling Points

Write your question here.
Hello. I am having a bit of a logic error with my code.
This is challenge 16 from chapter 13 from starting out with c++ 9th edition.
Program Output:
The temperature ethyl:
 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149`` ``````#include using namespace std; // Create a class called TempPoints class TempPoints { private: int temperature; public: TempPoints(); int isEthylFreezing(int); int isEthylBoiling(int); int isOxygenFreezing(int); int isOxygenBoiling(int); int isWaterFreezing(int); int isWaterBoiling(int); void setTemperature(int); int getTemperature(); }; // Default constructor TempPoints::TempPoints() { int temperature = 0; } // Determine if Ethyl alcohol is freezing int TempPoints::isEthylFreezing(int ethylCold) { if (ethylCold <= -173) { cout << "The ethyl's temperature is cold" << endl; return true; } return false; } // Determine if the Ethyl alcohol is boiling int TempPoints::isEthylBoiling(int ethylHot) { if (ethylHot >= 172) { cout << "The ethyl's temperature is hot" << endl; return true; } return false; } // Determine if the oxygen is freezing int TempPoints::isOxygenFreezing(int oxyCold) { if (oxyCold <= -362) { cout << "The oxygen's temperature is cold" << endl; return true; } return false; } // Determine if the oxygen is boiling int TempPoints::isOxygenBoiling(int oxyHot) { if (oxyHot >= -306) { cout << "The oxygen's temperature is hot" << endl; return true; } return false; } // Determine if the water is freezing int TempPoints::isWaterFreezing(int coldWater) { if (coldWater <= 32) { cout << "The water's temperature is cold" << endl; return true; } return false; } // Determine if the water is boiling int TempPoints::isWaterBoiling(int hotWater) { if (hotWater >= 212) { cout << "The water's temperature is hot" << endl; return true; } return false; } // Set up the temperature void TempPoints::setTemperature(int temp) { temperature = temp; } // Retrieve the temperature int TempPoints::getTemperature() { return temperature; } // Prompt the user to enter the temperature for the following void printTempInfo(TempPoints &tempInput) { int ethyl, oxygen, water; cout << "Temperature for ethyl: "; cin >> ethyl; tempInput.getTemperature(); cout << "Temperature for oxygen: "; cin >> oxygen; tempInput.getTemperature(); cout << "Temperature for water: "; cin >> water; tempInput.getTemperature(); } // Evaluate the temperature conditions for each item void printTempPoints(TempPoints tempAmounts) { int ethyl, oxygen, water; if (tempAmounts.isEthylFreezing(ethyl)) { cout << tempAmounts.isEthylFreezing(ethyl) << endl; } if (tempAmounts.isEthylBoiling(ethyl)) { cout << tempAmounts.isEthylBoiling(ethyl) << endl; } if (tempAmounts.isOxygenFreezing(oxygen)) { cout << tempAmounts.isOxygenFreezing(oxygen)<< endl; } if (tempAmounts.isOxygenBoiling(oxygen)) { cout << tempAmounts.isOxygenBoiling(oxygen) << endl; } if (tempAmounts.isWaterFreezing(water)) { cout << tempAmounts.isWaterFreezing(water) << endl; } if (tempAmounts.isWaterBoiling(water)) { cout << tempAmounts.isWaterBoiling(water) << endl; } }``````
Last edited on
1. Thank you for using code tags, they really help.

2. You accidentally double-posted your code, you should delete the 2nd copy. (delete lines 160-319)

3. You are using uninitialized variables in printTempPoints(). Where are you getting the values?

printTempInfo() looks like it is used to get the values, not printing temperature information as the function name might indicate, but the variables in that function are locally scoped to that function only.
4. Your default ctor at lines 22-25. You are defining a variable scoped to just the body of the ctor, not initializing your temperature data member.

1 possible change:
 ``22232425`` ``````TempPoints::TempPoints() { temperature = 0; }``````

Or:
 ``2223`` ``````TempPoints::TempPoints() : temperature { } { }``````

Or:
 ``89101112`` ``````int temperature { }; // .... elided code Temperature() {}``````
5. I wouldn't have a function's return type as int if it were returning a Boolean value (true/false).

It isn't wrong/bad, the intent would be better if the return type is bool.

There are several different ways to rewrite/refactor the code, depending on how complex you want to make the class. I don't own the book you are using, so I can't really comment on what the program is trying to teach.
 I am having a bit of a logic error with my code.

Which is? If the problem is a logic error, then using the debugger to trace through the code should pinpoint the issue.
I think you should re-consider your design!

Instead of having a separate `isFooFreezing()` and `isFooBoiling()` for each compound in your class, consider having just one `isFreezing()` and one `isBoiling()` function. The freezing/boiling temperature can be passed into the class in the constructor. Then create one instance (object) of your class for each compound:

 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344`` ``````class TempPoints { public: TempPoints(const int freezingTemp, const int boilingTemp); TempPoints::TempPoints(const TempPoints &other); bool TempPoints::isFreezing(const int temp) const; bool TempPoints::isBoiling(const int temp) const; private: const int freezingTemp; const int boilingTemp; }; TempPoints::TempPoints(const int freezingTemp, const int boilingTemp) : freezingTemp(freezingTemp), boilingTemp(boilingTemp) { } TempPoints::TempPoints(const TempPoints &other) : freezingTemp(other.freezingTemp), boilingTemp(other.boilingTemp) { } bool TempPoints::isFreezing(const int temp) const { if (temp <= freezingTemp) { std::cout << "temperature is cold" << std::endl; return true; } return false; } bool TempPoints::isBoiling(const int temp) const { if (temp >= boilingTemp) { std::cout << "temperature is hot" << std::endl; return true; } return false; } int main() { TempPoints waterTempPoints(32, 212); TempPoints oxygenTempPoints(-362, -306); ... }``````

Could also organize your instances in a map:
 ``1234567891011121314151617`` ``````int main() { std::map myPoints; myPoints.insert(std::make_pair("water", TempPoints( 32, 212))); myPoints.insert(std::make_pair("oxygen", TempPoints(-362, -306))); ... const int temp[4] = { 666, 42, -333, -666 }; for (size_t i = 0; i < _countof(temp); ++i) { for (std::map::const_iterator iter = myPoints.cbegin(); iter != myPoints.cend(); ++iter) { std::cout << "Is " << iter->first << " boiling at " << temp[i] << "? --> " << (iter->second.isBoiling(temp[i]) ? "yes" : "no") << std::endl; std::cout << "Is " << iter->first << " freezing at " << temp[i] << "? --> " << (iter->second.isFreezing(temp[i]) ? "yes" : "no") << std::endl; } std::cout << std::endl; }``````

 ```Is oxygen boiling at 666? --> yes Is oxygen freezing at 666? --> no Is water boiling at 666? --> yes Is water freezing at 666? --> no Is oxygen boiling at 42? --> yes Is oxygen freezing at 42? --> no Is water boiling at 42? --> no Is water freezing at 42? --> no Is oxygen boiling at -333? --> no Is oxygen freezing at -333? --> no Is water boiling at -333? --> no Is water freezing at -333? --> yes Is oxygen boiling at -666? --> no Is oxygen freezing at -666? --> yes Is water boiling at -666? --> no Is water freezing at -666? --> yes```

👍
Last edited on
Perhaps:

 ``1234567891011121314151617181920212223242526272829303132333435`` ``````#include #include #include class TempPoints { public: TempPoints(int freezingTemp, int boilingTemp) : freezingTemp(freezingTemp), boilingTemp(boilingTemp) {} bool isFreezing(int temp) const { return temp <= freezingTemp; } bool isBoiling(int temp) const { return temp >= boilingTemp; } private: int freezingTemp {}; int boilingTemp {}; }; int main() { const std::map myPoints { {"water", {32, 212}}, {"oxygen", {-362, -306}}, {"ethyl", {-173, 172}} }; constexpr std::array temp { 666, 42, -333, -666 }; for (const auto& t : temp) { for (const auto& [nam, p] : myPoints) { std::cout << nam << " at " << t << " is a "; if (p.isBoiling(t)) std::cout << "gas\n"; else if (p.isFreezing(t)) std::cout << "solid\n"; else std::cout << "liquid\n"; } std::cout << '\n'; } }``````

 ``` ethyl at 666 is a gas oxygen at 666 is a gas water at 666 is a gas ethyl at 42 is a liquid oxygen at 42 is a gas water at 42 is a liquid ethyl at -333 is a solid oxygen at -333 is a liquid water at -333 is a solid ethyl at -666 is a solid oxygen at -666 is a solid water at -666 is a solid ```

Last edited on
The textbook requires that I have a freezing and boiling function individually for water, ethyl, and oxygen. The challenge is chapter 13 the introduction on classes. So I am not sure if I could use the suggestions you are offering since it doesn't follow the details of the problem properly.

Chapter 13(Introduction to Classes):
Challenge # 13: Freezing and Boiling Points
The problem states following:

Design a class called temperature with the appropriate accessor and mutator functions.
The member functions:
isEthylFreezing - This function only returns true if ethyl is freezing otherwise false.
isEthylBoiling - This function only returns true if ethyl is boiling otherwise false.
isOxygenFreezing - This function only returns true if oxygen is freezing otherwise false.
isOxygenBoiling - This function only returns true if ethyl is freezing otherwize false.
isWaterFreezing - This function only returns true if ethyl is freezing otherwise false.
isWaterBoiling - This function only returns true if ethyl is freezing otherwise false.

Write a program that designs a class. The program should ask the user to enter the temperature and display the list of substances that will either freeze or boil at that temperature. For example, if the user enters -20 the class would report that the water freezes and the oxygen will boil.

This is the logic error I was stating earlier in my previous post.
Program Output:
Temperature for ethyl: 12
Temperature for oxygen: 12
Temperature for water: 13
The oxygen's temperature is hot
The oxygen's temperature is hot
1
The temperature's water is cold.
The temperature's water is cold
1

The table the book uses
Substance
Ethyl Alcohol
Oxygen
Water

Freezing Point
-173
-362
32

Boiling Point
172
-306
212

Last edited on
Having separate functions (or separate classes) only makes sense if they actually implement a different logic. Having two or more functions (or classes) that basically do the same thing, just with different "built-in" constants, is a good example of how to not do things! It's redundant "copy & paste" code that bloats your program for no good reason. This makes you program harder to read and harder to maintain...

Whenever possible, you should try to generalize and parameterize things. So, instead of having n separate functions (or classes) that all do the same thing (except for some implicit constants), you should have just one function (or class) that can be parameterized as needed. In other words, make the implicit constant an explicit parameter. This makes your program a whole lot shorter. And, if you need to change or fix your code, then you need to do this in exactly one place – rather than having to change/fix your program in n separate places.

Really, I have seen too many "real world" projects where people created a complete copy of a 1000 lines "spaghetti code" function, just to change one tiny detail. Of course, there were bugs in the "original" function that ended up in the "copy" of that function too. And, of course, when those bugs later were fixed (by another person), it was only fixed it in the "original" function, but not in the "copy" of that function; other person did not scan the whole project for slightly modified copies of the same function that they just fixed. Needless to say, both functions were called in production code. Working with such project is a nightmare for programmer...
Last edited on
I was thinking of what you just mentioned.
I just wasn't sure if it made sense since the problem told to me to do that way.
I will try your suggestion and post an update.
If you really have to, because "the task" requires it, you can still do:

 ``123456789101112131415161718192021222324252627`` ``````#define DEF_SUBSTANCE_FUNC(NAME) \ static bool is##NAME##Freezing(const int temp) { return tp##NAME.isFreezing(temp); } \ static bool is##NAME##Boiling (const int temp) { return tp##NAME.isBoiling (temp); } #define DEC_SUBSTANCE_TP(NAME) \ static const TempPoints tp##NAME; #define DEF_SUBSTANCE_TP(NAME, X, Y) \ const TempPoints WrapperToSatisfyTask::tp##NAME = TempPoints((X), (Y)); class WrapperToSatisfyTask { public: DEF_SUBSTANCE_FUNC(Ethyl) DEF_SUBSTANCE_FUNC(Oxygen) DEF_SUBSTANCE_FUNC(Water) private: DEC_SUBSTANCE_TP(Ethyl) DEC_SUBSTANCE_TP(Oxygen); DEC_SUBSTANCE_TP(Water); }; DEF_SUBSTANCE_TP(Ethyl, -172, 173) DEF_SUBSTANCE_TP(Oxygen, -362, -306) DEF_SUBSTANCE_TP(Water, 32, 212)``````

 ``1234`` ``````int main() { WrapperToSatisfyTask::isWaterBoiling(42); }``````

...with the class `TempPoints` implemented as outlined in previous post:
https://cplusplus.com/forum/beginner/284096/#msg1230147
Last edited on
As per the book, then perhaps:

 ``12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364`` ``````#include class Temp { public: static bool isEthylFreezing(int temp) { return ethyl.isFreezing(temp); } static bool isEthylBoiling(int temp) { return ethyl.isBoiling(temp); } static bool isOxygenFreezing(int temp) { return oxygen.isFreezing(temp); } static bool isOxygenBoiling(int temp) { return oxygen.isBoiling(temp); } static bool isWaterFreezing(int temp) { return water.isFreezing(temp); } static bool isWaterBoiling(int temp) { return water.isBoiling(temp); } static void doEthyl(int t) { if (isEthylBoiling(t)) std::cout << "Ethyl is boiling\n"; if (isEthylFreezing(t)) std::cout << "Ethyl is freezing\n"; } static void doOxygen(int t) { if (isOxygenBoiling(t)) std::cout << "Oxygen is boiling\n"; if (isOxygenFreezing(t)) std::cout << "Oxygen is freezing\n"; } static void doWater(int t) { if (isWaterBoiling(t)) std::cout << "Water is boiling\n"; if (isWaterFreezing(t)) std::cout << "Water is freezing\n"; } private: class TempPoints { public: TempPoints(int freezingTemp, int boilingTemp) : freezingTemp(freezingTemp), boilingTemp(boilingTemp) {} bool isFreezing(int temp) const { return temp <= freezingTemp; } bool isBoiling(int temp) const { return temp >= boilingTemp; } private: int freezingTemp {}; int boilingTemp {}; }; const static inline TempPoints water { 32, 212 }; const static inline TempPoints oxygen { -362, -306 }; const static inline TempPoints ethyl { -173, 172 }; }; int main() { Temp temp; int t {}; std::cout << "Enter temperature (Fahrenheit): "; std::cin >> t; temp.doWater(t); temp.doEthyl(t); temp.doOxygen(t); }``````

 ``` Enter temperature (Fahrenheit): -20 Water is freezing Oxygen is boiling ```

Here is an update:

I have made some improvements however the issue I is when I input a value and the computer set the degrees to 0 for Farhenheit. I realize its because I haven't enter anything that deals with the print function I made.

So any suggestions for the user input.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160`` ``````#include using namespace std; // Create a class called Tempeature class Temperature { private: int temperature; public: Temperature(); Temperature(int); bool isEthylFreezing(); bool isEthylBoiling(); bool isOxygenFreezing(); bool isOxygenBoiling(); bool isWaterFreezing(); bool isWaterBoiling(); int getTemperature(); }; // Default Constructor Temperature::Temperature() { temperature = 0; } // Constructor Temperature::Temperature(int temp) { temperature = temp; } // Accessor int Temperature::getTemperature() { return temperature; } // Determine if the ethyl is freezing bool Temperature::isEthylFreezing() { int ethylCold = -173; if (getTemperature() <= ethylCold) { return true; } return false; } // Determine if the ethyl is boiling bool Temperature::isEthylBoiling() { int ethylHot = 172; if (getTemperature() >= ethylHot) { return true; } return false; } // Determine if the oxygen is freezing bool Temperature::isOxygenFreezing() { int oxyFreeze = -362; if (getTemperature() <= oxyFreeze) { return true; } return false; } // Determine if the oxygen is boiling bool Temperature::isOxygenBoiling() { int oxyBoil = -306; if (getTemperature() >= oxyBoil) { return true; } return false; } // Determine if the water is freezing bool Temperature::isWaterFreezing() { int coldWater = 32; if(getTemperature() <= coldWater) { return true; } return false; } // Determine if the water is boiling bool Temperature::isWaterBoiling() { int hotWater = 212; if(getTemperature() >= hotWater) { return true; } return false; } void isFreezing(Temperature freezing) { cout << "These substances are freezing at " << freezing.getTemperature() << " degrees F: " << endl; if (freezing.isEthylFreezing()) { cout << "Ethyl" << endl; } if (freezing.isOxygenFreezing()) { cout << "Oxygen" << endl; } if (freezing.isWaterFreezing()) { cout << "Water" << endl; } } void isBoiling(Temperature boiling) { cout << "These substances are boiling " << boiling.getTemperature() << " degress F: " << endl; if (boiling.isEthylBoiling()) { cout << "Ethyl" << endl; } if (boiling.isOxygenBoiling()) { cout << "Oxygen" << endl; } if (boiling.isWaterBoiling()) { cout << "Water" << endl; } } void isPrintTemperature(Temperature temp) { int therometer; cout << "Enter a temperature in Fahrenheit: "; cin >> therometer; isFreezing(temp); isBoiling(temp); } // Main test driver int main() { Temperature points; isPrintTemperature(points); system("PAUSE"); return 0; }``````

Program Output:
Enter a temperature in Fahrenheit: 32
These substances are freezing at 0 degrees F:
Water
These substances are boiling at 0 degrees F:
Oxygen
Press any key to continue...
... or alternatively then:

 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162`` ``````#include class Temp { public: Temp(int t_) : t(t_) {} bool isEthylFreezing() const { return ethyl.isFreezing(t); } bool isEthylBoiling() const { return ethyl.isBoiling(t); } bool isOxygenFreezing() const { return oxygen.isFreezing(t); } bool isOxygenBoiling() const { return oxygen.isBoiling(t); } bool isWaterFreezing() const { return water.isFreezing(t); } bool isWaterBoiling() const { return water.isBoiling(t); } void display() const { if (isEthylBoiling()) std::cout << "Ethyl is boiling\n"; if (isEthylFreezing()) std::cout << "Ethyl is freeing\n"; if (isOxygenBoiling()) std::cout << "Oxygen is boilng\n"; if (isOxygenFreezing()) std::cout << "Oxygen is freezing\n"; if (isWaterBoiling()) std::cout << "Water is boiling\n"; if (isWaterFreezing()) std::cout << "Water is freezing\n"; } private: class TempPoints { public: TempPoints(int freezingTemp, int boilingTemp) : freezingTemp(freezingTemp), boilingTemp(boilingTemp) {} bool isFreezing(int temp) const { return temp <= freezingTemp; } bool isBoiling(int temp) const { return temp >= boilingTemp; } private: int freezingTemp {}; int boilingTemp {}; }; const static inline TempPoints water { 32, 212 }; const static inline TempPoints oxygen { -362, -306 }; const static inline TempPoints ethyl { -173, 172 }; int t {}; }; int main() { int t {}; std::cout << "Enter temperature (Fahrenheit): "; std::cin >> t; Temp temp(t); temp.display(); }``````

Last edited on
Topic archived. No new replies allowed.