Number of Years

G

Gregc.

G'day

I'm trying to work out the number of years since 1970, here is my code:

include <stdio.h>
#include <time.h>


const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;


int secToYear(int seconds) //Function Protoype
{
seconds = (SEC_IN_YEAR);
return (seconds);
}


main () {
time_t now = time(0);
printf("%i seconds since 1/1/1970\n",secToYear(now));


}

For some reason the answer is coming out as 1. Could someone offer me
some guidance.

Thankyou

Greg
 
J

John F

Gregc. said:
G'day

I'm trying to work out the number of years since 1970, here is my
code:

include <stdio.h>

You missed # here.
#include <time.h>


const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;

This ends up as 31536000 which does not fit an int.
Use long instead.

why not just:

const long SEC_IN_YEAR=365*24*60*60;

since this is the only constant you are using.
int secToYear(int seconds) //Function Protoype

This is not a prototype. It is the implementation.
{
seconds = (SEC_IN_YEAR);
return (seconds);

OK... you take the parameter "seconds", assign a constant and return
that...?
I have no clue about what you intend to do here. I suppose some
calculations...
}


main () {

int main() would be the correct way since the standard requires main()
to return an int.
time_t now = time(0);
printf("%i seconds since 1/1/1970\n",secToYear(now));

return EXIT_SUCCESS;
}

For some reason the answer is coming out as 1. Could someone offer
me
some guidance.

Thankyou

Greg

regards
John
 
O

osmium

Gregc. said:
I'm trying to work out the number of years since 1970, here is my code:

include <stdio.h>
#include <time.h>


const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;


int secToYear(int seconds) //Function Protoype
{
seconds = (SEC_IN_YEAR);

You are ignoring the parameter passed to the function,. You are simply
ignoring the value of now, which you provided in the caller, and overwriting
it. I suspect there is something else too, but this is the first thing I
notice.
 
J

John F

Richard Heathfield said:
John F said:


Yes, it is.

I knew that someone here would beat me up on this.
That, too. But it *is* a prototype.

In this case yes because of the top-down structure of his code.

Anyway to me a prototyoe does have a semicolon at the end of line...
;-)
Limits confusion of my students. I tell them ; following the bracket
indicates a declaration while an expression is a definition and that a
definition can substitute a declaration. That covers most cases, I
think.

regards
John
 
V

Vladimir S. Oka

I knew that someone here would beat me up on this.


In this case yes because of the top-down structure of his code.

It always is. There just may be no code further below that uses it.
;-)
 
N

Nick Keighley

Gregc. said:
I'm trying to work out the number of years since 1970, here is my code:

include <stdio.h>
#include <time.h>

const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;

int secToYear(int seconds) //Function Protoype
{
seconds = (SEC_IN_YEAR);
return (seconds);
}

main () {
time_t now = time(0);
printf("%i seconds since 1/1/1970\n",secToYear(now));
}

For some reason the answer is coming out as 1. Could someone offer me
some guidance.

I must be missing something. Why not just calculate the current year
(use localtime()) then subtract 1970?
 
R

Rod Pemberton

Gregc. said:
G'day

I'm trying to work out the number of years since 1970, here is my code:
For some reason the answer is coming out as 1. Could someone offer me
some guidance.

It's easier for me to show you. I'd also recommend buying or checking out
from a library:
"C: A Reference Manual," by Samuel Harbison and Guy Steele, Jr. of Tartan
Laboratories.


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct tm es;
time_t esr;
int delta_years;

int main(void)
{
esr=time(NULL);
es=*localtime(&esr);
delta_years=1900+es.tm_year-1970;
/* Yes, I know I can just subtract 70. It may help the OP. */

printf("%d years since 1/1/1970\n",delta_years);
printf("%ld seconds since 1/1/1970\n",(unsigned long)esr);

exit(EXIT_SUCCESS);
}


Rod Pemberton
 
K

Keith Thompson

Gregc. said:
so would it be localtime()-1970?

So *what* would be localtime()-1970?

You need to provide enough context so each followup makes sense on its
own. Read <http://cfaj.freeshell.org/google/> to learn how and why.

Going back to the previous article, the answer to your question is no.
Your system should provide documentation for the localtime() function.
If it doesn't, a Google search should find some documentation for it.
 
R

Richard G. Riley

G'day

I'm trying to work out the number of years since 1970, here is my code:

include <stdio.h>
#include <time.h>


const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;


int secToYear(int seconds) //Function Protoype
{
seconds = (SEC_IN_YEAR);
return (seconds);
}


main () {
time_t now = time(0);
printf("%i seconds since 1/1/1970\n",secToYear(now));


}

For some reason the answer is coming out as 1. Could someone offer me
some guidance.

Thankyou

Greg

Have a close look at your secToYear() function. There's a start.

You have not programmed what you set out to get : you are simply
getting a constant.

Use a debugger or put a printf in your secToYear function : you are
setting seconds to a constant on each call.

Finally nowhere in your code are you doing a "difference" calculation.

Good luck!
 
K

Keith Thompson

Gregc. said:
I'm trying to work out the number of years since 1970, here is my code:

include <stdio.h>
#include <time.h>


const int SEC_IN_MIN = 60;
const int SEC_IN_HOUR = SEC_IN_MIN * 60;
const int SEC_IN_DAY = SEC_IN_HOUR * 24;
const int SEC_IN_YEAR = SEC_IN_DAY * 365;


int secToYear(int seconds) //Function Protoype
{
seconds = (SEC_IN_YEAR);
return (seconds);
}


main () {
time_t now = time(0);
printf("%i seconds since 1/1/1970\n",secToYear(now));


}

For some reason the answer is coming out as 1. Could someone offer me
some guidance.

Does it really? When I compile it (after adding the missing '#' on
the first line), I get:

tmp.c:6: error: initializer element is not constant
tmp.c:7: error: initializer element is not constant
tmp.c:8: error: initializer element is not constant

You're probably using a C++ compiler (C++ has different rules about
initializers than C).

The easiest fix for that is to move the const declarations inside the
secToYear() function. Also, "main ()" should be "int main(void)", and
you should have a "return 0;" at the end of your main function.

When I moved the const declarations inside the function, I got the
following output:

31536000 seconds since 1/1/1970

The program simply prints the value of SEC_IN_YEAR, which doesn't
match either the problem description, the message in the printf
statement, *or* the output you say it produced.

The program could be corrected to work the way you seemed to intend it
to work, but only by assuming that time() returns the number of
seconds since 1970-01-01. That's a common implementation, but it's
not guaranteed by the language, and you shouldn't depend on it if you
want your code to be portable (or if you want to post it here).

Is this the actual code you compiled? Did it really print 1 when you
ran it?
 
M

Mark McIntyre

On 11 Mar 2006 21:33:46 -0800, in comp.lang.c , "Gregc."

(please don't snip attributions, its important to knwo who said what.
I've reinserted them for convenience)
(also, don't top post in CLC, it annoys the regulars and makes posts
hard to read)
John F said
Thanks for your help. What I am trying to produce is 36 years ie
2006-1970.

Then do some calculations inside secToYear(). You might want to read
up on the functions in time.h, especially ones that convert to and
from a time_t and a struct tm. You might also want to look at the
contents of the struct tm.

Mark McIntyre
 
E

Eric Sosman

John said:
You missed # here.




This ends up as 31536000 which does not fit an int.

"Which might not fit in an int" would be better.
Use long instead.

why not just:

const long SEC_IN_YEAR=365*24*60*60;

Because if 31536000 does not fit in an int, this
will initialize SEC_IN_YEAR to the wrong value. (If
it manages to initialize SEC_IN_YEAR at all, that is:
this might be undefined behavior.)
 
J

John F

Eric Sosman said:
"Which might not fit in an int" would be better.

Correct. Depends on the underlying width ... uint32_t would be better
in this case, if it exists.
Because if 31536000 does not fit in an int, this
will initialize SEC_IN_YEAR to the wrong value. (If
it manages to initialize SEC_IN_YEAR at all, that is:
this might be undefined behavior.)

Are you sure about this?

6.7.8 [4] could lead to this conclusion.
"All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals."

So one could argue that a multiplication of numeric literals is not a
constant expression?

Whereas [11] states: " The initializer for a scalar shall be a single
expression, optionally enclosed in braces. The initial value of the
object is that of the expression (after conversion); the same type
constraints and conversions as for simple assignment apply, taking the
type of the scalar to be the unqualified version of its declared
type."

So we look at assignment: 6.5.16
[3] "An assignment operator stores a value in the object designated by
the left operand. An assignment expression has the value of the left
operand after the assignment, but is not an lvalue. The type of an
assignment expression is the type of the left operand unless the left
operand has qualified type, in which case it is the unqualified
version of the type of the left operand."

6.5.16.1 [2] "In simple assignment (=), the value of the right operand
is converted to the type of the assignment expression and replaces the
value stored in the object designated by the left operand."

I read this as if 365*24*60*60 will be cast to long. especially since
it will be cast to long in case of multiplication. See 6.3.1.8

Comments requested (I want to gain on knowledge of the Standard:)!

regards
John
 
J

John F

<Correction Reference to 6.3.1.8 does not deal with integer types>

John F said:
Eric Sosman said:
"Which might not fit in an int" would be better.

Correct. Depends on the underlying width ... uint32_t would be
better in this case, if it exists.
Because if 31536000 does not fit in an int, this
will initialize SEC_IN_YEAR to the wrong value. (If
it manages to initialize SEC_IN_YEAR at all, that is:
this might be undefined behavior.)

Are you sure about this?

6.7.8 [4] could lead to this conclusion.
"All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals."

So one could argue that a multiplication of numeric literals is not
a constant expression?

Whereas [11] states: " The initializer for a scalar shall be a
single expression, optionally enclosed in braces. The initial value
of the object is that of the expression (after conversion); the same
type constraints and conversions as for simple assignment apply,
taking the type of the scalar to be the unqualified version of its
declared type."

So we look at assignment: 6.5.16
[3] "An assignment operator stores a value in the object designated
by the left operand. An assignment expression has the value of the
left operand after the assignment, but is not an lvalue. The type of
an assignment expression is the type of the left operand unless the
left operand has qualified type, in which case it is the unqualified
version of the type of the left operand."

6.5.16.1 [2] "In simple assignment (=), the value of the right
operand is converted to the type of the assignment expression and
replaces the value stored in the object designated by the left
operand."

I read this as if 365*24*60*60 will be cast to long. especially
since it will be cast to long in case of multiplication.

See 6.3.1.8

This reference is not correct. It takes care of float/double
conversion.
Sorry for this slipping in.
Comments requested (I want to gain on knowledge of the Standard:)!


regards
John
 
E

Eric Sosman

John said:
Correct. Depends on the underlying width ... uint32_t would be better
in this case, if it exists.



Are you sure about this?

Yes. All three multiplications follow the rules for `int'
arithmetic, after which the result is converted to `long'. If
the product is too large for `int', Evil Things will happen.
I'm feeling lazy at the moment and disinclined to hunt through
the Standard to figure out whether the Evil Things amount to
undefined behavior or to a guarantee of an implementation-
defined incorrect result; the fact that they're Evil is enough
for me.
> I read this as if 365*24*60*60 will be cast to long. especially since
> it will be cast to long in case of multiplication. See 6.3.1.8

There is no cast in what you showed. Adding a cast would
be one way to repair the problem:

const long SEC_IN_YEAR = (long)365 * 24 * 60 * 60;

Another would be to use one or more `long' numbers to begin
with:

const long SEC_IN_YEAR = 365L * 24 * 60 * 60;

As you noted in a follow-up, 6.3.1.8 doesn't apply here.
 
J

John F

Eric Sosman said:
[SNIP]
Are you sure about this?

Yes. All three multiplications follow the rules for `int'
arithmetic, after which the result is converted to `long'. If
the product is too large for `int', Evil Things will happen.

I can see it now. I usually do not encounter it on my 32 bit targets
where both long and int are 32 bits wide.
That's why I was not so sure at first. But you are right it is a
matter of portability.
I'm feeling lazy at the moment and disinclined to hunt through
the Standard to figure out whether the Evil Things amount to
undefined behavior or to a guarantee of an implementation-
defined incorrect result; the fact that they're Evil is enough
for me.

;-) well you are right. Evil is evil.
There is no cast in what you showed. Adding a cast would
be one way to repair the problem:

const long SEC_IN_YEAR = (long)365 * 24 * 60 * 60;

Another would be to use one or more `long' numbers to begin
with:

const long SEC_IN_YEAR = 365L * 24 * 60 * 60;

Yes. That would put it on the safe side with "32 portable-street".
As you noted in a follow-up, 6.3.1.8 doesn't apply here.

I just misread the passage when parsing the standard.

thanks and regards
John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,501
Latest member
Ledmyplace

Latest Threads

Top