What's wrong with my C++ temperature convertor? - visual-studio-2010

I'm trying to write a program that takes a value in the Fahrenheit scale, validates the value to ensure that it is legitimate, and returns the proper value for Fahrenheit, Celsius, and Newton.
The code below keeps giving error messages for Lines 21, 25, 29 (The void's)
#include <iostream>
using namespace std;
class temperature {
public:
double getFahrenheit();
double getCelsius();
double getNewton();
void setFahrenheit();
void setCelsius();
void setNewton();
private:
double fahrenheit, Celsius;
double c, f;
};
void freezing.setFahrenheit(){
f = 32;
fahrenheit = f;
}
void freezing.setCelsius(){
c = (5.0/9.0) * ( f - 32);
celsius = c;
}
void freezing.setNewton(){
n=(33.0/100.0)*c;
newton=n;
double freezing.getFahrenheit(){
return fahrenheit;
}
double freezing.getCelsius(){
return Celsius;
}
Double freezing.getNewton(){
Return Newton;
}
int main() {
Temperature freezing(32);
Freezing.setFahrenheit(); Freezing.setCelsius();
Freezing.setNewton();
cout << "water freezes at " << freezing.getFahrenheit() << " Fahrenheit, " << freezing.getCelsius() << " Celisus, and " << freezing.getNewton() << " Newton" << endl;
return 0;
}

You need to use :: instead of . Moreover, your class is called temperature and not freezing
void temperature::setFahrenheit()
See also this question
There's a few other errors too:
void temperature::setCelsius(){ //and not void freezing.setCelsius
c = (5.0/9.0) * ( f - 32);
celsius = c;
}
Here you reference celsius , but the temperature class defines Celsius with a captial C.
void freezing.setNewton(){
n=(33.0/100.0)*c;
newton=n;
Here you use the n and newton variables, but you have not defined them anywhere. They should perhaps be members of your temperature class.
Double freezing.getNewton(){
Return Newton;
}
Here you have capital letters, which doesn't make sense, it should be
double temperature::getNewton(){
return newton; //you need to make this a member variable of your class too..
}
Temperature freezing(32);
Your temperature class has a lowercase t , the Temperature class doesn't exist.
And there's no constructor defined, so you can't pass 32 in there.
Freezing.setFahrenheit();
Freezing.setCelsius();
These 2 lines references Freezing, but you called your variable freezing

Related

Why does this C++ closure produce different outputs?

I am trying to learn the concept of closures in C++. I have the following code.
std::function<void(void)> closureWrapper2()
{
int x = 10;
return [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
}
int main()
{
std::function<void(void)> func2 = closureWrapper2();
// std::cout << "---" << std::endl;
func2();
func2();
func2();
}
Output
Value in the closure: 11
Value in the closure: 12
Value in the closure: 13
Now if I uncomment the cout statement I get the following output.
Output
---
Value in the closure: 32765
Value in the closure: 32766
Value in the closure: 32767
Can anyone please explain why printing something before the function calls changes the output?
std::function<void(void)> closureWrapper2()
{
int x = 10;
return [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
}
It's undefined behaviour(a) to dereference a pointer to, or use a reference to, an object after that object no longer exists. That's what you're doing here. You capture a reference to x then attempt to use it after x has ceased to exist.
It's a local (automatic storage duration) variable inside closureWrapper2() so ceases to exist when that function exits.
That may appear to work without the cout line but that doesn't make it any less undefined. Putting the cout line is almost certainly modifying the stack where x was originally stored, changing the starting value.
You can get a similar effect with (in my environment):
void otherFn() { int abc = 97, def = 42, ghi = 9; std::cout << abc+def+ghi << '\n'; }
int main()
{
std::function<void(void)> func2 = closureWrapper2();
otherFn();
func2();
func2();
func2();
}
This indicates that the original value is definitely being overwritten by the abc variable in otherFn():
148
Value in the closure: 98
Value in the closure: 99
Value in the closure: 100
I had to try varying numbers of arguments as the stack frames for the closureWrapper2() and otherFn() are most likely different. Calling cout.operator<<() is likely to go through a number of stack levels to achieve its end so will be more likely to overwrite the original value.
(a) This is the solution to your problem, of course: don't do undefined behaviour :-)

c++ : unordered map with pair of string_viewes

Here is a code snippet I have :
struct PairHasher {
size_t operator()(const std::pair<std::string_view, std::string_view>& stop_stop) const {
return hasher(stop_stop.first) + 37*hasher(stop_stop.second);
}
std::hash<std::string_view> hasher;
};
BOOST_FIXTURE_TEST_CASE(unordered_map_string_view_pair_must_be_ok, TestCaseStartStopMessager)
{
const std::vector<std::string> from_stops = {"from_0", "from_1", "from_2"};
const std::vector<std::string> to_stops = {"to_0", "to_1", "to_2"};
std::unordered_map<std::pair<std::string_view, std::string_view>, std::int32_t, TransportCatalogue::PairHasher> distance_between_stops;
for ( std::size_t idx = 0; idx < from_stops.size(); ++idx) {
std::cout << from_stops[idx] << " : " << to_stops[idx] << std::endl;
distance_between_stops[std::pair(from_stops[idx], to_stops[idx])] = idx;
}
std::cout << "MAP CONTENT :" << std::endl;
for (auto const& x : distance_between_stops)
{
std::cout << x.first.first << " : " << x.first.second << std::endl;
}
}
I expect to see 3 pairs inside the container, but there is only 1 concerning to the output :
MAP CONTENT :
from_2 : to_2
So, where are two more pair lost? What am I doing wrong?
Moving my comment to an answer.
This is pretty sneaky. I noticed in Compiler Explorer that changing:
distance_between_stops[std::pair(from_stops[idx], to_stops[idx])] = idx;
to
distance_between_stops[std::pair(std::string_view{from_stops[idx]}, std::string_view{to_stops[idx]})] = idx;
fixes the bug. This hints that the problem lies in some implicit string -> string_view conversion. And indeed that is the case, but it is hidden behind one extra layer.
std::pair(from_stops[idx], to_stops[idx]) creates a std::pair<std::string, std::string>, but distance_between_stops requires a std::pair<std::string_view, std::string_view>. When we insert values into the map, this conversion happens implicitly via overload #5 here:
template <class U1, class U2>
constexpr pair(pair<U1, U2>&& p);
Initializes first with std::forward<U1>(p.first) and second with std::forward<U2>(p.second).
This constructor participates in overload resolution if and only if std::is_constructible_v<first_type, U1&&> and std::is_constructible_v<second_type, U2&&> are both true.
This constructor is explicit if and only if std::is_convertible_v<U1&&, first_type> is false or std::is_convertible_v<U2&&, second_type> is false.
(For reference, std::is_constructible_v<std::string_view, std::string&&> and std::is_convertible_v<std::string&&, std::string_view> are both true, so we know this overload is viable and implicit.)
See the problem yet? When we use the map's operator[], it has to do an implicit conversion to create a key with the proper type. This implicit conversion constructs a pair of string_views that are viewing the temporary memory from the local pair of strings, not the underlying strings in the vector. In other words, it is conceptually similar to:
std::string_view foo(const std::string& s) {
std::string temp = s + " foo";
return temp;
}
int main() {
std::string_view sv = foo("hello");
std::cout << sv << "\n";
}
Clang emits a warning for this small example, but not OP's full example, which is unfortunate:
warning: address of stack memory associated with local variable 'temp' returned [-Wreturn-stack-address]
return temp;
^~~~

C++ Struct attributes can change within function, but remain unchanged outside scope of function

I'm working on a self imposed challenge which involves implementing a linked list and an append function for it, which is giving me issues seemingly related to variable scope.
The append function loops through each link element until it reads a NULL value and then changes the data value associated with that link to the function input. The test outputs within the function seem to show it is working as intended, but when performing the same test outside the function, even after it is called gives a different output.
template <class T>
struct atom{
T data;
atom<T>* link = NULL;
};
template <class T>
void append_LL(atom<T> first, T input_data){
atom<T>* current_node = &first;
atom<T>* next_node = current_node->link;
int i = 0;
while (i < 4 && next_node != NULL) {
current_node = next_node;
next_node = next_node->link;
i ++;
}
current_node->data = input_data;
current_node->link = (atom<T>*)malloc(sizeof(atom<T>));
cout << "leaving node as: " << current_node->data << endl; //outputs 5
cout << "input nodes data: " << first.data << endl; //outputs 5
}
int main() {
int dd = 5;
atom<int> linked_list;
linked_list.data = 999;
append_LL(linked_list, dd);
cout << linked_list.data << endl; //outputs 999
}
Because you are not sending the same atom. You see the program is making a copy of the linked_list in the main function and sending that copy to the function.
If you want to modify the same linked_list then change
void append_LL(atom<T> first, T input_data){
to
void append_LL(atom<T> &first, T input_data){
That way you are sending the really atom not a copy of it.

Constructing an object as part of ostream output

For a class declaration as below:
class A{
public:
A(int);
~A()
private:
int a;
};
And a constructor definition as follows:
A::A(int i){
a = i;
cout << a << endl;
}
I would like to do something like this from main():
int main(){
int i;
//user input for value
//stored inside i
cout << "The value is " << A obj(i);
return 0;
}
I now get the following error for the above code in main():
error: 'A' does not refer to a value
What is the cause of this error?
You cannot declare obj and output it on the same line. If you want obj to remain available after printing, do this:
A obj(i);
cout << "The value is " << obj;
Otherwise, skip obj in favor of a temporary object:
cout << "The value is " << A(i);
You cannot have a declaration in the middle of another line.
What you can do is create an A on the fly with casting (A) i, or simply A(i), this will cast the int i into an A, and then send it to cout. The temporary A object is then directly discarded.
If you want to keep it, you have to declare a name for it, in its own statement.
You need to first output the message "The value is " on first code line. On the second code line you create the object obj of type A which will output the i.
int main()
{
int i;
cout << "The value is ";
A obj(i);
return 0;
}

How does return by rvalue reference work?

Just when I thought I kind of understand rvalue reference, I ran into this problem. The code is probably unnecessarily long, but the idea is quite simple. There is a main() function, and returnRValueRef() function.
#include <iostream>
#define NV(x) "[" << #x << "=" << (x) << "]"
#define log(x) cout << __FILE__ << ":" << __LINE__ << " " << x << endl
using namespace std;
class AClass {
public:
int a_;
AClass() : a_(0) {
log("inside default constructor");
}
AClass(int aa) : a_(aa) {
log("inside constructor");
}
int getInt() const {
return a_;
}
void setInt(int a) {
a_ = a;
}
AClass(AClass const & other) : a_(other.a_) {
log("inside copy constructor");
}
AClass & operator=(AClass const & rhs) {
log("inside assignment operator" << "left value" << NV(a_) << "right value" << NV(rhs.a_));
a_ = rhs.a_;
return *this;
}
AClass & operator=(AClass && rhs) {
log("inside assignment operator (rvalue ref)" << "left" << NV(a_) << "right" << NV(rhs.a_));
a_ = rhs.a_;
return *this;
}
};
AClass && returnRValueRef() {
AClass a1(4);
return move(a1);
}
int main() {
AClass a;
a = returnRValueRef();
}
Okay, I would expect this code to first print "inside default constructor" (for a), then "inside constructor" (for a1), and then assignment operator message with rhs.a_ = 4. But the output is
testcpp/return_rvalue_ref.cpp:14 inside default constructor
testcpp/return_rvalue_ref.cpp:17 inside constructor
testcpp/return_rvalue_ref.cpp:39 inside assignment operator (rvalue ref)left[a_=0]right[rhs.a_=0]
Can somebody explain why the last line in the output prints right[rhs.a_=0] instead of right[rhs.a_=4]? I thought the move() just makes lvalue into rvalue without changing its contents. But I am clearly missing something.
Thanks so much for your help. :-)
Edit: I think I know what might be going on. May be the destructor for a1 in function returnRValueRef() is being called when it goes out of scope (even if it is turned into rvalue), and after that the memory location for a1 (or rvalue reference for it) contains undefined stuff! Not sure if that is what is happening, but seems plausible.
An rvalue reference is still a reference. In your case, you are referencing the local variable that has been destructed. Therefore it is undefined behavior to access the members. What you want to do is to return the object:
AClass returnRValueRef() {
AClass a1(4);
return move(a1);
}
However, a move happens automatically with a local variable, so you really only need to do this:
AClass returnRValueRef() {
AClass a1(4);
return a1;
}

Resources