numerical result out of range

M

Maximilian

Hello group!

I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example

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

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

When I run this, output is

s: (null)
errno: 34 (Numerical result out of range)

What is wrong?

What is numerical result?

I use lcc-win32 compiler.

Greetings, Maximilian
 
L

Lew Pitcher

Hello group!

I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example

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

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

When I run this, output is

s: (null)
errno: 34 (Numerical result out of range)

What is wrong?

Well, AFAICT, you didn't initialize the tm structure properly.

Your initialization set tm_mday to 0 (it should be between 1 and 31
inclusive), and left a number of the rest of the structure members set to
inconsistant values.
What is numerical result?

Jacob should be able to answer why asctime() uses that specific error code.
I use lcc-win32 compiler.

Greetings, Maximilian

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
I

Ian Collins

Maximilian said:
Hello group!

I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example

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

int main(void)
{
struct tm tm = { 0 };

Check the specification for struct tm (hint - what's the range for tm_mday).
 
I

Ian Collins

Ian said:
Check the specification for struct tm (hint - what's the range for
tm_mday).
Following on, you said:
> errno = 0;
> s = asctime(&tm);
> e = errno;
> printf("s: %s\n", s);
> printf("errno: %i (%s)\n", e, strerror(e));
>
> return 0;
> }
>
> s: (null)
> errno: 34 (Numerical result out of range)
>
> What is wrong?

I think this violates the requirements for asctime. The standard
defines the algorithm and it does not check for valid month days, so the
conforming output should be

s: Sun Jan 0 00:00:00 1900

I assume you didn't invoke the compiler in conforming mode.
 
K

Keith Thompson

Maximilian said:
I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example

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

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

When I run this, output is

s: (null)
errno: 34 (Numerical result out of range)
[...]

Since lcc-win is developed by jacob navia, who has been involved in
some rather heated discussions here about the behavior of asctime() in
corner cases, including the particular case you use in your program, I
have to wonder whether this is a serious question.

If you seriously want to format dates, you should probably use
strftime() rather than asctime(). If you really want to use
asctime(), you should limit its arguments to reasonable values.

(I know what the standard says about how your program should behave.
If you really want to know, I'll be glad to explain it. If you don't
post a followup, I'll assume you don't.)
 
M

Maximilian

Maximilian said:
I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example

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

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

When I run this, output is

s: (null)
errno: 34 (Numerical result out of range)
[...]

Hello, Keith Thompson!
Since lcc-win is developed by jacob navia, who has been involved in
some rather heated discussions here about the behavior of asctime() in
corner cases, including the particular case you use in your program, I
have to wonder whether this is a serious question.

That is very mysterious. I searched comp.lang.c in google and
found nothing. I thought lcc-win32 uses msvcrt.dll.
If you seriously want to format dates, you should probably use
strftime() rather than asctime(). If you really want to use
asctime(), you should limit its arguments to reasonable values.

That program (tm_mday=0) is only example. asctime() also returns NULL
if tm_mday is > 31, but not if date is for example February 31.

What I wonder is why I can not format "alien" dates with asctime(). In
my game all months have 32 days (because it's power of 2). Can strftime()
format months with 32 days, everywhere? What means "Numerical result" in
context of asctime()?
(I know what the standard says about how your program should behave.
If you really want to know, I'll be glad to explain it. If you don't
post a followup, I'll assume you don't.)

Yes please, I want to know!

Greetings, Maximilian
 
K

Keith Thompson

Maximilian said:
Maximilian said:
I write adventure game in language C and when I want to format
date, it is "Numerical result out of range".

For example [snip]
s: (null)
errno: 34 (Numerical result out of range)
[...]

Hello, Keith Thompson!
Since lcc-win is developed by jacob navia, who has been involved in
some rather heated discussions here about the behavior of asctime() in
corner cases, including the particular case you use in your program, I
have to wonder whether this is a serious question.

That is very mysterious. I searched comp.lang.c in google and
found nothing. I thought lcc-win32 uses msvcrt.dll.

I believe lcc-win32 uses its own runtime library. I don't know
whether it also uses msvcrt.dll, but jacob has said here that lcc-win
has its own implementation of astime(). If you're curious, you can
ask in comp.compilers.lcc.
That program (tm_mday=0) is only example. asctime() also returns NULL
if tm_mday is > 31, but not if date is for example February 31.

What I wonder is why I can not format "alien" dates with asctime(). In
my game all months have 32 days (because it's power of 2). Can strftime()
format months with 32 days, everywhere? What means "Numerical result" in
context of asctime()?

It seems fairly obvious that the numeric result you're giving it for
the day of the month is outside its range of 1..31. Whether the
implementation is allowed to reject such a value is another question.
Yes please, I want to know!

Ok. You can get a copy of a recent draft of the standard at
<http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>; asctime()
is described in 7.23.3.1. The definition hasn't changed significantly
since the 1989 ANSI C standard.

The behavior of asctime is defined, not in terms of hours, minutes,
seconds, and so forth, but by a specific algorithm, presented in C
code, to which it must be equivalent. An implementation that uses
that algorithm, or an equivalent one, will produce certain
well-defined results for certain input values -- even if those input
values are not sensible. For example, the day of the month is
formated with "%3d", which means that any value for mday in the range -99 to
+999 will fit in that 3-character field; longer values may cause a buffer
overrun *unless* the year, which is printed with "%d" takes up fewer
spaces.

jacob has rather strongly expressed the opinion that the input values
are required to be within the "normal ranges" defined in 7.23.1 (a
section that doesn't mention asctime), and that an implementation is
therefore free to behave differently (say, by returning NULL and
setting errno) if, for example, you give it a tm_mon value of 0, even
though the presented algorithm has well-defined behavior in that case.

(We've had several lengthy and unpleasant flame wars on that topic,
both here and in comp.std.c. You can understand my suspicion when
someone brings up an unusual example, using jacob's compiler, that
illustrates the very point that has been disputed. If someone wanted
to resurrect that old flame war, just for the fun of watching people
argue about it all over again, your original article might be an
effective way to do it. We do have people here who deliberately
disrupt this newsgroup. I hope that's not what you're doing. Search
for "asctime" in this newsgroups archives.)

So, having said all that, and assuming you're really interested in a
solution to your stated problem, my recommendation is *not* to use
asctime(). Setting aside the debates about how asctime() is required
to behave, it's primarily intended to handle dates that are valid in
the real-world Gregorian calendar. And it produces a rigid and
somewhat obsolete format. It automatically ends the string with a
new-line, it ignores localization, always using English abbreviations
for weekdays and months, and it uses an inconvenient ordering.

If you want to format alien dates, such as February 31 or January 0,
just format them yourself using sprintf(). (strftime() won't work for
your purposes; the result when any input values are outside their
"normal ranges" is unspecified.)
 
J

jacob navia

Maximilian wrote:

Hello Maximilian

Maybe you can help me out?

When I run this program under "Microsoft Visual C" 64 bits I get a
dialog box

"Test.exe has stopped working"

Below it is written

"Windows is searching for a solution to this problem"

Why is this so?

Here is my program:

d:\lcc\test>type numresult.c
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <string.h>

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

Greetings

Jacob
 
K

Keith Thompson

ie. to values inconsistant with the struct tm field values

No, tm_mday is the only required member of struct tm for which 0 is
outside the "normal range".

For his stated purposes, so are time(), localtime(), and strftime().
 
L

Lew Pitcher

Lew Pitcher said:




No, it set the rest of the structure members to 0.

which are values that are (or may be) inconsistant with each other.
For instance
- tm_wday will be 0, indicating that the selected date was a Sunday. Was
Jan 0, 1900 a Sunday?
- tm_yday will be 0, indicating that the selected date was 0 days since
January 1. Was January 0, 1900 zero days after January 1, 1900?
- tm_isdst will be 0, indicating that daylight-savings time was not in
effect. Was DST in effect on January 0, 1900?
The OP needs to look up time(), localtime(), and strftime(). The
asctime() function is a dead end.

Agreed, wrt the "real" calendar.
However, since the OP has since indicated that he is not working with
a "real" calendar (he has written his own, in which all months have 32
days), none of the C standard time and date functions will suffice for his
purposes.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
K

Keith Thompson

Lew Pitcher said:
However, since the OP has since indicated that he is not working with
a "real" calendar (he has written his own, in which all months have 32
days), none of the C standard time and date functions will suffice for his
purposes.

In some cases, this is because the C standard functions aren't defined
to work values outside their "normal" ranges. In other cases, it's
because some vendors have chosen to give enforcement of "reasonable"
arguments a higher priority than strict conformance to the standard.
 
M

Maximilian

Maximilian wrote:

Hello Maximilian

Maybe you can help me out?

When I run this program under "Microsoft Visual C" 64 bits I get a
dialog box

"Test.exe has stopped working"

Below it is written

"Windows is searching for a solution to this problem"

(Did it find one?)

Why is this so?

I don't know. Can MS asctime() return NULL, as well? I think "%s"
format specifier need not accept NULL pointer, but is common extension.

I'm more worried that asctime() returns NULL at all. I always looked
at it as simple formatter for struct tm, and as long as weekday and month
are in range, and as long as result string is not too long, I assumed it
would not try to look at values and simply use them as is.

Oddly, it seems February 31 is accepted but January 32 is not.

What about metric time?
Here is my program:

d:\lcc\test>type numresult.c
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <string.h>

int main(void)
{
struct tm tm = { 0 };
char *s;
int e;

errno = 0;
s = asctime(&tm);
e = errno;
printf("s: %s\n", s);

Perhaps

printf("s: %s", s ? s : "NULL\n");

is is better protection. My excuse is, I have never seen asctime()
return NULL pointer before.
printf("errno: %i (%s)\n", e, strerror(e));

return 0;
}

Greetings, Maximilian
 
K

Keith Thompson

Maximilian said:
(Did it find one?)



I don't know. Can MS asctime() return NULL, as well? I think "%s"
format specifier need not accept NULL pointer, but is common extension.

I think I already pointed you to
<http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf>. Read the
section on asctime().

There are no circumstances in which asctime() is specifically
permitted to return a null pointer. There are circumstances in which
its behavior is undefined; in those cases, returning a null pointer is
one possibility, but crashing your program is another.

Also, the standard says nothing about asctime setting errno. In my
opinion, it's not permitted to do so except in circumstances that
invoke undefined behavior.
I'm more worried that asctime() returns NULL at all. I always looked
at it as simple formatter for struct tm, and as long as weekday and month
are in range, and as long as result string is not too long, I assumed it
would not try to look at values and simply use them as is.

Oddly, it seems February 31 is accepted but January 32 is not.

In my opinion, the implementation you describe does not conform to the
standard. We can tell you what the standard specifies; if an
implementation fails to conform, you'll need to take it up with the
vendor. The vendor might not agree with my interpretation of the
standard.

Or, better yet, just don't use asctime(). I don't believe it's really
suitable for your purposes, and I think you're wasting time. You can
write your own solution (based on the algorithm given in the standard
if you like) far more easily than you can resolve these questions.
What about metric time?

What the heck is "metric time"?

[...]
Perhaps

printf("s: %s", s ? s : "NULL\n");

is is better protection. My excuse is, I have never seen asctime()
return NULL pointer before.

That will protect you against asctime() returning a null pointer. It
will not protect you against anything else.

[...]
 
J

jacob navia

Maximilian said:
is is better protection. My excuse is, I have never seen asctime()
return NULL pointer before.

POSIX specifies NULL return for errors
 
I

Ian Collins

jacob said:
POSIX specifies NULL return for errors

It says if the function is unsuccessful, it shall return NULL. But is
still specifies the standard algorithm and it does not define
"unsuccessful". It does not list any errors.

I didn't realise POSIX applied to windows.
 
B

Bill M

Keith said:
OK, sorry for the provocative subject :) Honestly, why
can't you let the Christians be? I don't believe in a god
either, but what's with the endless rants? What do you
hope to achieve?

More sanity and less forced religion in society!
 
L

lawrence.jones

Keith Thompson said:
Also, the standard says nothing about asctime setting errno. In my
opinion, it's not permitted to do so except in circumstances that
invoke undefined behavior.

Nope -- 7.5p3:

The value of errno may be set to nonzero by a library function
call whether or not there is an error, provided the use of errno
is not documented in the description of the function in this
International Stand ard.
 
K

Keith Thompson

Nope -- 7.5p3:

The value of errno may be set to nonzero by a library function
call whether or not there is an error, provided the use of errno
is not documented in the description of the function in this
International Stand ard.

Ah, good point.

However, an asctime() implementation that sets errno in circumstances
that don't invoke undefined behavior would not be equivalent to the
algorithm presented in the standard. So one could argue this point
either way, but I'm not going to bother.
 

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,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top