C++ homework help(solved thx)...

bGIveNs33

Golden Member
Jul 10, 2002
1,543
0
71
I'm trying to convert Celsius temps to Fahrenheit and output them to the screen. The temps need to come from a file and it needs to loop until it hits -999(sentinel value)

I've been messing around with this all afternoon and I can't seem to get it to work, which is odd because it was assignment 3 out of 6 for homework, so it should have been easy. Here is what I have-

Code:
#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;
  
int main() 
{ 
  
  double sentinel = -999;
  double f=0;
  double c=0;
  
  ifstream fin;
  fin.open("temps.txt");
  if (!fin.good()) throw "I/O error";
  
  while (true) 
  { 
   
    fin >> c;
    fin.ignore(1000, 10);
    
    if (c = -999) break;
        
    f = (9.0 / 5) * c + 32; 
    cout << "The temperature in degrees F is " << f << endl;
    
  } // while 
  
  return 0; 
} // main
 
Last edited:

degibson

Golden Member
Mar 21, 2008
1,389
0
0
I'm glad you got it, with help. C++ is pretty hard to learn. If you're interested, here is some advice on your specific solution from what most folks on this forum would call 'the grumpy low-level language guy'.

I've added my stuff as comments...
Code:
#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;
  
int main()     // It's better practice to use the standard prototype for main: main(int argc, char* argv[])
{ 
  
  double sentinel = -999;  // This doesn't change... how about 'const double sentinel = -999.0;' instead?
  double f=0; // When initializing floating types, use a floating literal, like '0.0'
  double c=0; 
  
  ifstream fin;
  fin.open("temps.txt");
  if (!fin.good()) throw "I/O error";
  
  while (true)  // why not 'while( c != sentinel )' ?
  // for that matter, why not 'while( c != sentinel && fin.good() )' ?
  { 
   
    fin >> c;
    fin.ignore(1000, 10);
    
    if (c = -999) break; // -999.0 would be better here... or better yet... use that 'sentinel' value from above
        
    f = (9.0 / 5) * c + 32; // mixing literal types is dubious. Better: 'double f = (9.0/5.0)*c+32.0;'
    cout << "The temperature in degrees F is " << f << endl;
    
  } // while 
  
  return 0; 
} // main
 

bGIveNs33

Golden Member
Jul 10, 2002
1,543
0
71
really good feedback... I'm going to incorporate what I can into the assignment.
 

dinkumthinkum

Senior member
Jul 3, 2008
203
0
0
I don't know what compiler you are using, but I know gcc will give warnings about that kind of usage. Also a debugger would have helped you.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Classic beginners mistake. You'll probably make it a few times more. We all do.

I forgot to mention: that really is a common mistake, and everybody does it. One thing you can do to help yourself a little bit is to get in the habit of writing:
Code:
if( 7 == a ) { ... }
instead of:
Code:
if( a == 7 ) { ... }

Because 7 isn't an lvalue (aka, isn't an assignable left-hand-side of an = operator).

I've never managed to train myself to do this, btw, but I think that it's a good practice, as it in theory prevents mistakes (some people say 7 == a is less readable, however).
 

Leros

Lifer
Jul 11, 2004
21,867
7
81
I forgot to mention: that really is a common mistake, and everybody does it. One thing you can do to help yourself a little bit is to get in the habit of writing:
Code:
if( 7 == a ) { ... }
instead of:
Code:
if( a == 7 ) { ... }

Because 7 isn't an lvalue (aka, isn't an assignable left-hand-side of an = operator).

I've never managed to train myself to do this, btw, but I think that it's a good practice, as it in theory prevents mistakes (some people say 7 == a is less readable, however).

Interestingly enough, we discovered that the order can sometimes have a substantial effect on the amount of assembly code generated. At work we had a scenario where "var == func()" and "func() == var" generated drastically different amounts of assembly. It was almost a 10x difference.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Interestingly enough, we discovered that the order can sometimes have a substantial effect on the amount of assembly code generated. At work we had a scenario where "var == func()" and "func() == var" generated drastically different amounts of assembly. It was almost a 10x difference.

Thats not too surprising... order of evaluation must be considered, along with any side effects. (I don't know if there is a constraint on evaluation order of RHS/LHS of == or not ... ).
 

Barnaby W. Füi

Elite Member
Aug 14, 2001
12,343
0
0
I forgot to mention: that really is a common mistake, and everybody does it. One thing you can do to help yourself a little bit is to get in the habit of writing:
Code:
if( 7 == a ) { ... }
instead of:
Code:
if( a == 7 ) { ... }

Yeah, but then you have to learn to think like Yoda. It's a bit awkward. Just crank up your compiler's warning output (-Wall -pedantic with gcc) and it'll warn you for that usage. And if you really want to do it (sometimes you might), then you can surround it with an extra set of parentheses and it won't warn you anymore.
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Interestingly enough, we discovered that the order can sometimes have a substantial effect on the amount of assembly code generated. At work we had a scenario where "var == func()" and "func() == var" generated drastically different amounts of assembly. It was almost a 10x difference.

Which case generated more assembly code?

Did you guys find an explanation (or even have some guesses) for what was going on? This sounds useful to know.

Edit: I believe in a == b, 'a' is evaluated before 'b' (i.e., left to right). That doesn't really help me figure out which case generated more assembly though... my thinking is:
1) in both cases, the return value of func() will be loaded into the register for returns.
2) in both cases, var will be in another register
3) CMP those 2 registers & check the cpu flag

Does it get more complicated if func() has side-effects that affect 'var'? I'm thinking it won't unless 'var' is volatile, in which case loading var will probably occur twice in 'var == func()'.
 
Last edited:

degibson

Golden Member
Mar 21, 2008
1,389
0
0
...
2) in both cases, var will be in another register
...

I'm not sure about this assumption. After executing func(), it is reasonable to assume that var is no longer register-allocated. Though I'm not really seeing 10x difference from that.

Now I'm curious. Here's a little experiment I just ran. foo.C:
Code:
  1 #include <stdio.h>
  2 
  3 int foo();
  4 
  5 void smile(int var) {
  6   if( var == foo() ) {
  7     printf("Chrome\n");
  8   }
  9 }
 10 
 11 void meh(int var) {
 12   if( var == foo() ) {
 13     printf("Firefox\n");
 14   }
 15 }

Here's the output of 'g++ -o foo.S -S -O3 foo.C':

Function smile():
Code:
 34 .globl _Z5smilei
 35   .type _Z5smilei, @function
 36 _Z5smilei:
 37 .LFB14:
 38   pushq &#37;rbx
 39 .LCFI1:
 40   movl  %edi, %ebx
 41   call  _Z3foov
 42   cmpl  %ebx, %eax
 43   je  .L11
 44   popq  %rbx
 45   ret
 46   .p2align 4,,7
 47 .L11:
 48   popq  %rbx
 49   movl  $.LC1, %edi
 50   jmp puts

Function meh():
Code:
  8 .globl _Z3mehi
  9   .type _Z3mehi, @function
 10 _Z3mehi:
 11 .LFB15:
 12   pushq %rbx
 13 .LCFI0:
 14   movl  %edi, %ebx
 15   call  _Z3foov
 16   cmpl  %ebx, %eax
 17   je  .L6
 18   popq  %rbx
 19   ret
 20   .p2align 4,,7
 21 .L6:
 22   popq  %rbx
 23   movl  $.LC0, %edi
 24   jmp puts

The functions appear to have the same length, and are in all aspects identical -- they even use the same return position optimization at .L6 and .L11.
Perhaps a different compiler? I've tried -O0 thru -O3 on g++ and the output code doesn't change. Perhaps the expression for 'var' needs to be more complicated...?
 
Last edited:

tatteredpotato

Diamond Member
Jul 23, 2006
3,934
0
76
I love the direction this thread has gone. From a simple C syntax error to code generation and compiler optimizations.
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
Which case generated more assembly code?

Did you guys find an explanation (or even have some guesses) for what was going on? This sounds useful to know.

Edit: I believe in a == b, 'a' is evaluated before 'b' (i.e., left to right). That doesn't really help me figure out which case generated more assembly though... my thinking is:
1) in both cases, the return value of func() will be loaded into the register for returns.
2) in both cases, var will be in another register
3) CMP those 2 registers & check the cpu flag

Does it get more complicated if func() has side-effects that affect 'var'? I'm thinking it won't unless 'var' is volatile, in which case loading var will probably occur twice in 'var == func()'.

I could see it in the case of objects, however, I really can't see how a comp would be made that much more complex in the simple case of func() == primitive.

If operator overloading is some how applied, that might be it. But other then that, I don't know. Maybe it has something to do with a function returning by reference (Just because returning by reference can be evil )
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
I'm not sure about this assumption. After executing func(), it is reasonable to assume that var is no longer register-allocated. Though I'm not really seeing 10x difference from that.

Ooooooops. Wow I dunno what I was thinking there, lol. So as you said, maybe var has to be loaded more than once. Presumably if it's some kind of expression, it'd be stored, stack'd by the fcn call, and reloaded to a register later. Still can't imagine this difference, but at least it doesn't happen for simple cases as you've shown?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Ooooooops. Wow I dunno what I was thinking there, lol. So as you said, maybe var has to be loaded more than once. Presumably if it's some kind of expression, it'd be stored, stack'd by the fcn call, and reloaded to a register later. Still can't imagine this difference, but at least it doesn't happen for simple cases as you've shown?

Yes, I admit I'm a little bit baffled. But compilers do strange things sometimes -- maybe an inlined function would make the difference?
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Yes, I admit I'm a little bit baffled. But compilers do strange things sometimes -- maybe an inlined function would make the difference?

ooo I like that idea. Compilers usually only auto-inline small functions right? (I guess 10x as much asm could mean 1 line to 10 lines.) Alternatively the func() in question could've been defined with the inline keyword.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
ooo I like that idea. Compilers usually only auto-inline small functions right? (I guess 10x as much asm could mean 1 line to 10 lines.) Alternatively the func() in question could've been defined with the inline keyword.

Indeed, though I'm not sure why the compiler would only inline in one case and not the other -- maybe it was to keep the other val register allocated?
 

Gamingphreek

Lifer
Mar 31, 2003
11,679
0
81
Indeed, though I'm not sure why the compiler would only inline in one case and not the other -- maybe it was to keep the other val register allocated?

Doesn't the 'inline' operator only SUGGEST that the compiler inline the function? From what I remember, the compiler doesn't have to follow that directive.

Still doesn't explain why one would be inlined and the other not.

-Kevin
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
Doesn't the 'inline' operator only SUGGEST that the compiler inline the function? From what I remember, the compiler doesn't have to follow that directive.

Still doesn't explain why one would be inlined and the other not.

-Kevin

inline is a STRONG suggestion. If the compiler deems that it can do it, it will. Something like

Code:
void inline foo()
{
    foo();
}

won't be inlined as the inlining stops with recursion.
 

Gamingphreek

Lifer
Mar 31, 2003
11,679
0
81
inline is a STRONG suggestion. If the compiler deems that it can do it, it will. Something like

Code:
void inline foo()
{
    foo();
}
won't be inlined as the inlining stops with recursion.

Which is one of the reasons why recursion is horribly inefficient as an equivalent conditional loop can be unrolled (to an extent), correct?

Does VS2008 have a way for me to view the assembly code generated for the functions. I would like to look into that latter part of this thread as well, but I only have VS2008 here at work.

-Kevin
 

Cogman

Lifer
Sep 19, 2000
10,283
134
106
Which is one of the reasons why recursion is horribly inefficient as an equivalent conditional loop can be unrolled (to an extent), correct?

Does VS2008 have a way for me to view the assembly code generated for the functions. I would like to look into that latter part of this thread as well, but I only have VS2008 here at work.

-Kevin

For your second question (You should realize that Visual studios puts out masm compatable code, which means it uses intel syntax for its assembly, "mov dst, src" vs "movl $src, &#37;dst" I personally prefer the intel syntax)
http://codegem.org/2008/10/generate-assembly-from-c-code-in-visual-studio

As for the first. Not so much. The reason recursion is trumped by an iterative loop is because calling a function usually has a fair amount of overhead, loading and unloading the stack frame pointer is really quite expensive. Not to mention that if the function changes any register it has to save and restore that register (ok, that really depends on the calling convention... Either way, that has to be saved somehow). Not to mention that return addresses have to be pushed onto the stack.

With an iterative loop, much of that overhead disappears. The looping variable is often stored in a register, no stack frame saving, and (depending on the loop size) a significantly reduced amount of stack operations.

Loop unrolling, while helpful, isn't the recursion killer.
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
inline is a STRONG suggestion. If the compiler deems that it can do it, it will.

Nope. The standard makes it clear that "inline" is only a suggestion. If or how willingly the compiler follows that suggestion is totally implementation defined.

AFAIK on modern version of MSVC (8/9/10) "inline" is pretty much pointless - all functions are inlined or not based on the compiler's cost/benefit analysis regardless of how they're declared. MSVC does give you the __forceinline keyword, but even then the compiler doesn't always follow the suggestion.
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |