Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Help! This is written just like another program I have done which works fine! I have listed variables, all float. My placeholders are all %.2f Compiler error pasted below also. Below the compiler errors, I have pasted my other program that "works". They are similar, only the non working program has an extra line of printf and scanf before outputting the answer. What's wrong??


Code:
#include <stdio.h>   

main ( )
{

	float price ; 
	float eps ;
	float pem = (price/eps) ;
	
	printf ("Enter Current Stock Price: ") ;
	scanf  ("%.2f", &price) ;
	
	printf ("Enter Current Earnings Per Share: ") ;
	scanf  ("%.2f", &eps) ;
	pem =  (price/eps) ;
	
	printf ("PEM: %.2f\n", pem) ;
	
	return 0 ;
	
}	

Scott-Deans-MacBook-Pro:documents scottdean$ gcc ~/documents/pem.c
/Users/scottdean/documents/pem.c: In function ‘main’:
/Users/scottdean/documents/pem.c:14: warning: unknown conversion type character ‘.’ in format
/Users/scottdean/documents/pem.c:17: warning: unknown conversion type character ‘.’ in format


Working program:

#include <stdio.h>

main ( )
{

	int r ;
	float pi = 3.14 ;
	float volume = (4.0/3.0)*(pi)*(r*r*r) ;
	
	printf ("Enter radius of sphere: ") ;
	scanf  (" %d" , &r ) ;
	volume = (4.0/3.0)*(pi)*(r*r*r) ;
	
	printf ("Volume of a sphere: %.2f\n" , volume) ;
	
	return 0 ;
}
 
Last edited by a moderator:

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Yep, your first suggestion did the trick. Man, staring at this code for 2 hours and I checked my book and it says that %f shows 6 places after the decimal, and to specify you can use %.1f, or %.2f or %.3f, etc, etc. BUT since your suggestion worked, what I did must only be valid in the call of printf, not scanf.

Thanks and happy new year! I'm learning this so I can move on to Objective C.
 

Sander

macrumors 6502a
Apr 24, 2008
521
67
The "number of significant digits" modifier works for printf, but not for scanf. Also, your code should read

Code:
int main(void)
{
    // rest of your code here
}

Finally, it seems you're coming from an Excel background - you are assigning things to variables by using functions, but C doesn't work that way (i.e., "pem" and "volume" aren't automatically updated as soon as one of the variables it's based on changes). Your code works because you specify the formula again later, but it's still dangerous to do it this way (and there should have been a warning about this): In determining "pem", you devide "price" by "eps", but neither has been assigned a value yet. They might hold zero, so running your program is likely to get a divide-by-zero. Had the variables been ints, that would have given you a program termination.

Hope that helps,
Sander
 

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
Format specifier for scanf is different to printf

Mitthrawnuruodo is right.

The format specifiers for scanf and printf are not the same. See http://www.cplusplus.com/reference/clibrary/cstdio/scanf/ for details of the allowable format specifiers for scanf.

I'm also concerned about the line:

Code:
float pem = (price/eps) ;

This line is using the price and eps variables before they are initialised. You're basically dividing two unknown numbers at this point. Worse, if eps happens to be zero, you'll be in hell of undefined behaviour. You might find your program crashing randomly at start up.

The initialisation is not necessary at this point. So I can sleep better tonight, please change it to:

Code:
float pem ;
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Thanks all,

Jiminaus, when I specify

float pem = (price / eps), I know the values aren't determined yet, but aren't I just declaring pem at this point (as a float) and declaring it's value, which will be input by the user later?

Just curious, but it is easer to do it your way.
Thanks

No I have no Excel background at all. I have no idea how to use Excel.. I'm teaching myself C so I can move on to Objective C. Just trying to follow my book, C programming by KN King, I'm only on Chapter 3!!

Thanks and happy new year!

Sander:

Your right, when I ran my program again, and entered 0 as the eps, I got an answer of inf.

However, it seems I can enter a negative eps, such as -2.44, and it outputs a negative number.

So how can I accommodate a zero input by the user? The call of scanf can include decimals, but doesn't have to. Why can't the user enter a zero?

Thanks
 
Last edited by a moderator:

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
This is no later. Unless you do some kind of loop (which you probably haven't encountered yet), code runs from the top to the bottom.

At any line, the lines before have been done before and won't be done again; and the lines after will be done after and have not bearing on the current line.

At the time the line declaring pem is executed, only the values of price and eps at that point are used. That line is exactly the same as the following 2 lines:

Code:
float pem ;
pem = (price / eps) ;

So, at the start of your program, the first thing your code does is divide price by eps and store the result in pem. At this point, price and eps have no defined value.

The code then goes on to do the 2 printf's and 2 scanf's.

Then again it divides prices by eps and stores the result in pem, replacing the result stored in pem at the start of the program.

This only happens because you coded that line. It has nothing to do with the fact you put = (price / eps) in declaration of pem.

The code then does the last printf just before returning (exiting).

BTW That was my first post in 2011!!!!! Sydney just entered the new year. Happy New Year everyone!!!!!!
 
Last edited by a moderator:

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
when I specify

float pem = (price / eps), I know the values aren't determined yet, but aren't I just declaring pem at this point (as a float) and declaring it's value, which will be input by the user later?

You are not. You are declaring pem and initialising it at the same time to an undefined value which involves dividing two undefined values. This is exceedingly bad. Asking for trouble on a massive scale. Instant fail. Totally unacceptable.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
C is an iterative language. Code is run line by line, and the statements are evaluated using the values of the variables at the time the line executes. There is a class of concurrent languages that acts more like what you are expecting, but you are not using one. You cannot "set" a variable to an expression that is kept up-to-date as elements of the expression change. The right operand of = is evaluated once while the statement is bring evaluated, and the result is stored in the left operand.

Obviously with loops and the dreaded goto a statement can be run multiple times, but this is still iterative, running the body of the loop iteratively.

-Lee
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
You are not. You are declaring pem and initialising it at the same time to an undefined value which involves dividing two undefined values. This is exceedingly bad. Asking for trouble on a massive scale. Instant fail. Totally unacceptable.

Wow, thanks, you sound so strict, like a teacher!! lol I appreciate the feedback, it is invaluable!! Thanks so much!!
 

Sander

macrumors 6502a
Apr 24, 2008
521
67
You will not exactly get a crash, like jiminaus ominously predicted. Division by zero in floating point is defined behavior (but wrong, as you noticed: Division by zero defaults to "division by positive zero", giving infinity; but division by "unspecified zero" should yield "not-a-number"). Anyway, it's still bad practise to use undefined variables. The compiler might have warned you about this, too.

As to your later question about the users input: You will have to validate it yourself. If "eps" may not be zero, you should add a check for this. Something like this:

Code:
do
{
    printf("Enter Current Earnings Per Share: ");
    scanf("%f", &eps);
    if (eps == 0)
        printf("Earnings Per Share can not be zero\n");
} while (eps == 0)

(Incidentally, some programming languages have a "repeat .. until" construct, which would perhaps be more appropriate in this case).

A few additional remarks:

1. Someone will reply to this post saying it's Bad Karma to compare floating point values for equality. However, they are repeating Dogma. In the case above, "eps" is not the result of some calculation which may induce rounding errors, so comparing directly with zero is fine.
2. I don't think it's really forbidden for "Earnings Per Share" to be zero. So instead of prohibiting the user from entering zero, you should perhaps change the flow of your program and print out something like "PEM is undefined for zero EPS".
 

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
Floats: more than just numbers with a decimal point

Wow. Division by positive zero versus division by negative zero. Floats can have values for infinity and "not a number" :eek:. Time for me to dive into that IEEE spec that's always talked about. I had no idea of these things. :eek:
 

dmi

macrumors regular
Dec 21, 2010
162
33
Division by zero in floating point is defined behavior
It may be defined by the IEEE 754 or IEC 60559 Standard for Binary Floating-Point Arithmetic, but it is undefined behavior in the ANSI X3.159-1989 or ISO/IEC 9899 C programming language standard

Whether or not an implementation of the C programming language uses the IEC 60559 floating point standard is implementation defined.
A conforming program can use IEC 60559 features while guarded by
#ifdef _ _STDC_IEC_559_ _
#endif
When _ _STDC_IEC_559_ _ is defined, conformance to the IEC 60559 annex is indicated.
the IEC 60559 annex provides for a FE_DIVBYZERO exception according to the state of the FENV_ACCESS pragma unless it is in the initializer for an object with static storage duration

(if you don't understand all the caveats for when division by 0.0 is defined or permitted. it would be best to avoid it or to not depend on any particular expectation of what may happen)

And you should avoid computations with uninitialized variables in any case.
Using the value of an object while it is indeterminate is undefined behavior regardless of any implementation defined exceptions.
 

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
Wow, I'm glad I got my answer, this thread has gotten a bit over my head! I'm only on chapter 3!! But interesting nonetheless, and good to at least expose myself to some of these ideas, as they will come up again in the future I'm sure.
 

mac2x

macrumors 65816
Sep 19, 2009
1,146
0
King's book is excellent IMO; I have learned a lot from it (coming from Kochan's book, which is excellent too but less detailed). Stick with King and read it closely; he packs a ton of info in there. :)
 

SidBala

macrumors 6502a
Jun 27, 2010
533
0
Have you done any VHDL before?

IIRC, VHDL is one language where I've seen where you can set a relationship like

a = b+c

and then update the values for b or c to automatically get the new value for a.

Obviously, this is all done in hardware, so it is a totally different mechanism.
 

dmi

macrumors regular
Dec 21, 2010
162
33
a = b+c

and then update the values for b or c to automatically get the new value for a.
If you had reason to do that in C, you might use something like
int a(){ return b+c; } // although using global values this way may not be the best style
then evaluating a() automatically uses the current value of b and c

or
#define a (b+c)
//which could also create certain maintenance troubles
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.