How do I call a function taking only "const char *a"

R

RoughRyde

Hi all,

I'm totally new to C and hava a problem how to handle different types
of variables.

I have a function which which you call by:

double calcdiff(const char *old, const char *new)

I have at start two doubles that I need to convert in order to call the
above function. How would I go about to do that?

Thanks
 
C

Chris Dollin

RoughRyde said:
I'm totally new to C and hava a problem how to handle different types
of variables.

[Get a decent C book. Dripfeeding via newsgroup is slow.]
I have a function which which you call by:

double calcdiff(const char *old, const char *new)

You have a function called `calcdiff` which returns a `double` and
it takes two /strings/ as arguments?

Something is broken.
I have at start two doubles that I need to convert in order to call the
above function. How would I go about to do that?

If you want to get the string representation of a double value,
probably you should use `sprintf`. But I'd apply the Birmingham
principle [1] first. If `calcdiff` takes two strings representing
doubles, turns them into doubles, subtracts them, and returns the
result, then it's a pretty naff function (and if it doesn't, it's
been given a naff name: heads you lose, tails I win).

[1] "I wouldn't start from here."
 
F

Fred Kleinschmidt

RoughRyde said:
Hi all,

I'm totally new to C and hava a problem how to handle different types
of variables.

I have a function which which you call by:

double calcdiff(const char *old, const char *new)

I have at start two doubles that I need to convert in order to call the
above function. How would I go about to do that?

Thanks
You haven't given enough information. What does the function actually
do? What format are the inputs supposed to be in?

For example:

d = calcdiff( "3.555", "1.7E-16" );

or

d = calcdiff( "three and a half", "pi" );

If it is just the former, and the function does exactly what its name
implies, why don't you just use:

d = var1 - var2;
 
R

RoughRyde

What I want is to calculate the number of days between two dates.
Given my limited knowledge of C I found an example of this on the web
which looked as below. The problem is that I'm given indata as doubles.
So in order to take the easy way out I just wanted to convert those
doubles.

But if you have any other suggestions on how to solve this that's
appreciated.



double calcdiff(const char *old, const char *new)
{
struct tm t1 = {0};
struct tm t2 = {0};
time_t tt1 = {0};
time_t tt2 = {0};

stotm(&t1, old);
stotm(&t2, new);
tt1 = mktime(&t1);
tt2 = mktime(&t2);
if(tt1 != -1 && tt2 != -1)
{
long day = 0;
double d = difftime(tt1, tt2);
if(d < 0) d *= -1.0;
day = d / 86400;
return day;
}
else
{
return 0;
}

}

void stotm(struct tm *p, const char *s)
{
int i;
struct tm blank = {0};
*p = blank;

for(i = 0; i < 4; i++)
{
p->tm_year *= 10;
p->tm_year += *s++ - '0';
}
p->tm_year -= 1900;
for(i = 0; i < 2; i++)
{
p->tm_mon *= 10;
p->tm_mon += *s++ - '0';
}
--p->tm_mon;
p->tm_mday = 10 * (*s++ - '0');
p->tm_mday += *s++ - '0';

}



Fred Kleinschmidt skrev:
 
E

Ernie Wright

RoughRyde said:
What I want is to calculate the number of days between two dates.
Given my limited knowledge of C I found an example of this on the web
which looked as below. The problem is that I'm given indata as doubles.

What do the doubles contain? Without knowing that, it's pretty hard to
suggest what might work better.

Based on the code you posted, let's pretend that the doubles you're
given represent a date as

10000 * year + 100 * month + day

so that today's date would be 20061214.0. If that's the case, you can
replace the stotm() function with something like this,

void dtotm( struct tm *t, double d )
{
memset( t, 0, sizeof( *t ));
t->tm_year = ( int ) d / 10000 - 1900;
t->tm_mon = ( int ) fmod( d, 10000 ) / 100 - 1;
t->tm_mday = ( int ) fmod( d, 100 );
}

Change calcdiff() to accept double arguments rather than strings, and
replace calls to stotm() with dtotm().

But now you have another problem. If either of the dates is before
January 1, 1970, calcdiff() will fail. In many implementations, it'll
also fail if either date is after January 18, 2038. This is the range
of dates that can typically be stored in a value of type time_t.

If you need to work with dates outside this range, consider converting
them to Julian day numbers. This is the number of days since January 1,
4713 B.C. Today is JD 2454084, for example. You can subtract these
numbers directly to find the number of days between two dates. Code for
converting to JD is easily googled.

- Ernie http://home.comcast.net/~erniew
 
K

Keith Thompson

Ernie Wright said:
Based on the code you posted, let's pretend that the doubles you're
given represent a date as

10000 * year + 100 * month + day

so that today's date would be 20061214.0. If that's the case, you can
replace the stotm() function with something like this,

void dtotm( struct tm *t, double d )
{
memset( t, 0, sizeof( *t ));
t->tm_year = ( int ) d / 10000 - 1900;
t->tm_mon = ( int ) fmod( d, 10000 ) / 100 - 1;
t->tm_mday = ( int ) fmod( d, 100 );
}

Change calcdiff() to accept double arguments rather than strings, and
replace calls to stotm() with dtotm().

But now you have another problem. If either of the dates is before
January 1, 1970, calcdiff() will fail. In many implementations, it'll
also fail if either date is after January 18, 2038. This is the range
of dates that can typically be stored in a value of type time_t.

Typically, but not always. *Many* systems use a time_t representation
in which 0 represents January 1, 1970, but this is not specified in
the C standard. The standard says only that time_t is an arithmetic
type capable of representing times.
 
E

Ernie Wright

Keith said:
*Many* systems use a time_t representation in which 0 represents
January 1, 1970, but this is not specified in the C standard. The
standard says only that time_t is an arithmetic type capable of
representing times.

Thanks for the clarification.

It looks like the standard does *not* specify

the resolution (usually 1 second),
the epoch (the meaning of (time_t) 0, usually January 1, 1970),
a maximum time_t value (often LONG_MAX),
whether time_t is signed (whether (time_t) -1 is meaningful),
or whether a time_t is aligned to a standard time scale (e.g. UTC).

I'm a little surprised it's that vague.

- Ernie http://home.comcast.net/~erniew
 
C

CBFalconer

Ernie said:
Thanks for the clarification.

It looks like the standard does *not* specify

the resolution (usually 1 second),
the epoch (the meaning of (time_t) 0, usually January 1, 1970),
a maximum time_t value (often LONG_MAX),
whether time_t is signed (whether (time_t) -1 is meaningful),
or whether a time_t is aligned to a standard time scale (e.g. UTC).

I'm a little surprised it's that vague.

Why should you be surprised? When the standard was promulgated any
further specification of those items would have broken existing
code, and it was a specific objective to minimize such breakage.
It is always possible to wrap the standard in more restrictive
standards, e.g. Posix, but not to relax things.

Read the C99 Rationale (N897.pdf) which includes much of the C90
rationale.
 
K

Keith Thompson

Ernie Wright said:
Thanks for the clarification.

It looks like the standard does *not* specify

the resolution (usually 1 second),
the epoch (the meaning of (time_t) 0, usually January 1, 1970),
a maximum time_t value (often LONG_MAX),
whether time_t is signed (whether (time_t) -1 is meaningful),
or whether a time_t is aligned to a standard time scale (e.g. UTC).

I'm a little surprised it's that vague.

It's vaguer than that. There's no guarantee that time_t is an integer
type, or that the relationship between time_t values and actual time
is linear, or even that it's monotonic (i.e., that increasing time_t
values represent increasing times).

To take just one example, a conforming implementation could represent
the current time (2006-12-15 08:27:23 UTC) as the integer value
20061215082723 or as the floating-point value 20061215.082723. Or it
could use ranges of bits, rather than of decimal digits, to represent
the various fields. And so on.
 
E

Ernie Wright

CBFalconer said:
Ernie said:
I'm a little surprised [the standard re time_t is] that vague.

Why should you be surprised?

Partly ignorance. Not knowing what the standard said about it, I've
assumed it was along the lines of what POSIX says about it.

But also partly because, unless it's wrapped in something more rigorous
like POSIX, it can't be used portably and is almost useless. To quote
one example from the rationale,

Since no measure is given for how precise an implementation’s best
approximation to the current time must be, an implementation could
always return the same date [from time()] instead of a more honest
–1. This is, of course, not the intent.

And throw in Keith Thompson's observations here as well.

Basically, without knowing anything about the precision or the range,
you can't portably rely on time() and mktime() to do anything at all.

Correction to my previous post: time_t must be signed (in some vague
sense: it must be able to represent (time_t) -1), but since this is
used as an error return by time() and mktime(), as a practical matter it
usually cannot represent times before its epoch ((time_t) 0).

- Ernie http://home.comcast.net/~erniew
 
K

Keith Thompson

Ernie Wright said:
Correction to my previous post: time_t must be signed (in some vague
sense: it must be able to represent (time_t) -1), but since this is
used as an error return by time() and mktime(), as a practical matter it
usually cannot represent times before its epoch ((time_t) 0).

No, the value -1 can be converted to any arithmetic type, and the
result is always well defined. If time_t is, say, an unsigned 32-bit
integer, then (time_t)-1 has the value 2147483647.

There are good reasons to make time_t signed, as you point out, so it
can represent times before the epoch (whatever the epoch happens to
be, and assuming a direct relationship between time_t values and
actual times).

I wouldn't mind seeing the specification nailed down a bit in the next
standard. I suspect (though I'm not certain) that things could be
tightened up significantly without affecting any existing
implementations. Better, there should probably be a whole new time
interface without the holes in the current one (I think there was an
attempt to introduce such an interface for C99, but it wasn't ready in
time.
 
E

Ernie Wright

Keith said:
No, the value -1 can be converted to any arithmetic type, and the
result is always well defined. If time_t is, say, an unsigned 32-bit
integer, then (time_t)-1 has the value 2147483647.

Pretty sure it has the value 4294967295.

More importantly, I'm not sure what your "no" is in response to. If the
underlying representation is unsigned, it ipso facto doesn't provide any
obvious way of encoding dates prior to the epoch. If signed, there is
at least one date prior to the epoch that collides with a value reserved
to indicate an error. In both cases, it is "signed" in the sense that
it must be capable of representing a value that is portably expressible
in only one way: (time_t) -1.

The definition of time_t is so flaccid that all kinds of *un*obvious
encodings are valid, which is why I qualified what I wrote with phrases
like "in some vague sense" and "as a practical matter." Without those
qualifications, it would be difficult to say anything at all about what
a time_t can represent.

- Ernie http://home.comcast.net/~erniew
 
K

Keith Thompson

Ernie Wright said:
Pretty sure it has the value 4294967295.

D'oh! You're right, of course.
More importantly, I'm not sure what your "no" is in response to. If the
underlying representation is unsigned, it ipso facto doesn't provide any
obvious way of encoding dates prior to the epoch. If signed, there is
at least one date prior to the epoch that collides with a value reserved
to indicate an error. In both cases, it is "signed" in the sense that
it must be capable of representing a value that is portably expressible
in only one way: (time_t) -1.

The definition of time_t is so flaccid that all kinds of *un*obvious
encodings are valid, which is why I qualified what I wrote with phrases
like "in some vague sense" and "as a practical matter." Without those
qualifications, it would be difficult to say anything at all about what
a time_t can represent.

The "No" was in response to "time_t must be signed"; I should have
paid more attention to the following "in some vague sense". I don't
think of unsigned integer types as being "signed in some vague sense",
but I see what you mean.
 
E

Ernie Wright

Keith said:
The "No" was in response to "time_t must be signed"; I should have
paid more attention to the following "in some vague sense". I don't
think of unsigned integer types as being "signed in some vague sense",
but I see what you mean.

I probably wouldn't have put it exactly that way if I hadn't been in
mid-backpedal.

Thanks for the discussion. I hadn't looked very carefully at time_t
until now, and it was an eye-opener.

- Ernie http://home.comcast.net/~erniew
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top