I have an application which is requesting input from the user, and the input
can be a number, or a string. This then gets put through a CASE statement,
more or less as follows:
DEFINE
var CHAR(5)
PROMPT "Enter data: " FOR var
CASE
WHEN var>=1 AND var<=9999
DISPLAY "Var is a number"
WHEN var IS NOT NULL
DISPLAY "Var is a string"
END CASE
The problem I've got is that if the user enters a string, the program bombs
out with a "Character to numeric conversion error" at the first WHEN clause.
Lastly, does anyone know if there is a "catchall" WHEN statement (like the *
in a UNIX shell CASE statement).
Thanks for any suggestions!
Regards, Ben
Just use:
WHENEVER ANY ERROR CONTINUE
LET numeric_var = char_var
IF STATUS = -1213
THEN
.... it's not a number
END IF
WHENEVER ANY ERROR STOP .... or the original setting
instead of the case statement.
> Lastly, does anyone know if there is a "catchall" WHEN statement (like
> the * in a UNIX shell CASE statement).
Yes. Try OTHERWISE.
> Thanks for any suggestions!
No problem.
Cheers,
--
Mark.
+----------------------------------------------------------+-----------+
|Mark D. Stock - Informix SA http://www.informix.com |//////// /|
|mailto:mds...@informix.com FAQ http://www.iiug.org |///// / //|
| +-----------------------------------+//// / ///|
| Tel: +27 11 807 0313 |If it's slow, the users complain. |/// / ////|
| Fax: +27 11 807 2594 |If it's fast, the users keep quiet.|// / /////|
|Cell: +27 83 250 2325 |Therefore, "No news: travels fast"!|/ ////////|
+----------------------+-----------------------------------+-----------+
Write a 4GL callable "C" wrapper function for the "C" atol() function
or strtol() function which will return "0" for a string that does not
start with a digit. Or just check (var[1,1] < "0" OR var[1,1] > "9").
The latter will not catch a string that starts with digits but contains
non-numerics. You could have the "C" function perform both checks to
be certain. It can just return TRUE or FALSE and you can use the CASE
on that result
Art Kagel
> Lastly, does anyone know if there is a "catchall" WHEN statement (like the *
> in a UNIX shell CASE statement).
Yes the OTHERWISE clause.
I wrote one not too long ago:
FUNCTION DUMMY
WHENEVER ANY ERROR CONTINUE
END FUNCTION
FUNCTION not_an_int(incoming)
DEFINE incoming INTEGER
RETURN status
END FUNCTION
FUNCTION DUMMY2
WHENEVER ERROR ....
END FUNCTION
Then merely...
IF not_an_int(char_var) THEN ........
Note - I wouldn't swear to the WHENEVER syntax - I may have that slightly
off. Of course I don't have the function handy...
The trick is in to getting the compiler to not check status for your
conversion. Passing the char variable to a function which expects an int
implies a conversion and status gets set if it fails.
cheers
j.
Feel free to use this if you want it:
function is_number( wstr )
define wstr char( 30 )
define i, n smallint
if wstr = ' ' or wstr is null then
return FALSE
end if
let n = length( wstr )
for i = 1 to n
if wstr[ i ] <> ' ' then
exit for
end if
end for
if i < n then
if wstr[ i ] = '-' or wstr[ i ] = '+' then
let i = i + 1
end if
end if
for i = i to n
if not is_numeric( wstr[ i ] ) then
return FALSE
end if
end for
return TRUE
end function
function is_numeric( c )
define c char( 1 )
if ( c >= '0' and c <= '9' ) or c = '.' then
return TRUE
end if
return FALSE
end function
The only thing that it doesn't see are multiple decimal points.
Carlos.
---
Carlos Costa e Silva <c...@minimal.pt>
Minimal - Formação e Consultoria
R. Prof. Vitor Fontes 10 A/B
1600 Lisboa
Portugal
-----Original Message-----
From: Ben Knox [mailto:b...@dircon.net]
Posted At: Quinta-feira, 12 de Fevereiro de 1998 13:00
Posted To: informix
Conversation: Checking datatype of CHAR variable in 4GL
Subject: Checking datatype of CHAR variable in 4GL
Does anyone if there a function in Informix 4gl (version 4) which will
let
you check the contents of a CHAR variable to see whether or not it is a
valid number, without causing a numeric conversion error?
...
Regards, Ben
Nice try Jack.
That's what I've been doing for a long time, until I discovered that, starting
from 4gl 4.13, non fatal errors where added to the error log all the same :-(
Had to go down to c and resort to strtol...
Ciao,
Marco
_______________________________________________________________________________
Marco Greco, Catania, Italy mar...@linux.ctonline.it
rem radioterapia +39 95 447828 fax 446558
Informix faq http://www.iiug.org/techinfo/faq/informix.htm
4glworks http://www.ctonline.it/~marcog
Informix on Linux http://www.ctonline.it/~marcog/ifmxlinux.htm
Um, that's what the log is there for.
The point is: the program flow itself is unaffected.
If the log contents matter that much to you, you can stop and start
error logging when you change WHENEVER from STOP to CONTINUE and vice-versa.
--
Alan Denney yosemite_at_netcom.com
"I do not like this word 'bomb'. It is not a bomb. It is a device which
is exploding."
-- Jacques Le Blanc, French ambassador to New Zealand, referring to the
nuclear 'devices' France is testing in the South Pacific
That's exactly what I meant, Alan. Form errors (i.e. conversion errors, for
instance) are logged in the error log even after a WHENEVER ANY ERROR CONTINUE,
which obviously isn't the correct way of handling errors.
To make it more clear, this is the contents of my error log after running the
following useless program (4gl/c 4.16UC2 x SCO 3.2.5.0)
main
define a smallint
whenever any error continue
call startlog("error.log")
let a="a"
end main
Date: 02/15/1998 Time: 14:56:48
FORMS statement error number -1213.
Character to numeric conversion error
Ciao,
Marco
_______________________________________________________________________________
Marco Greco, Catania, Italy mar...@linux.ctonline.it
rem radioterapia +39 95 447828 fax 446558
Informix faq http://www.iiug.org/techinfo/faq/informix.htm
4glworks http://www.ctonline.it/~marcog
Informix on Linux http://www.ctonline.it/~marcog/ifmxlinux.htm
On on of our customer sites were are seeing ten's of these messages
per day. But we have over 250 programs in our product!!! How can
we hope to trace these problems when users don't even log them?
Or course eventally we'll end up with crap data in the database and
no idea where it came from...even a debugging enviroment variable to
cause a core dunp would be better than nothing...
--
David Williams
Maintainer of the Informix FAQ
Primary site (Beta Version) http://www.smooth1.demon.co.uk
Official site http://www.iiug.org/techinfo/faq/faq_top.html
I see you standin', Standin' on your own, It's such a lonely place for you, For
you to be If you need a shoulder, Or if you need a friend, I'll be here
standing, Until the bitter end...
So don't chastise me Or think I, I mean you harm...
All I ever wanted Was for you To know that I care
We did up an error routine once which was invoked on the whenever clause.
It captured everything there was to get from the SQLCA record, whatever it
could interpret from that data (error message, table, column, etc) and then
went out and checked the executable in question - doing a 'what' which told
us what version of everything was built into the executable - popped all of
this into a nice error message and mailed it to $ADMIN. Not that hard to
do up - the only issue is changing your 'whenever' clause in each module
and adding an 'ident' variable to store the RCS header info.
But then I have a little utility...
cheers
j.
David Williams <d...@smooth1.demon.co.uk> on 02/15/98 06:09:53 PM
Please respond to David Williams <d...@smooth1.demon.co.uk>
To: inform...@iiug.org
cc: (bcc: Jack Parker/Boston50/Epsilon)
Subject: Re: Checking datatype of CHAR variable in 4GL
Alan Denney writes:
> If the log contents matter that much to you, you can stop and start
> error logging when you change WHENEVER from STOP to CONTINUE and vice-versa.
What's the format of the 4GL statement to stop error logging when you
change WHENEVER from STOP to CONTINUE ? I tested for an undocumented
"STOPLOG()", but that wasn't found.
I ended up adding multiple startlog() lines to the program, using the
true logfile as the parameter when I have a "whenever any error call ... "
directive active, and "/dev/null" as the logfile parameter when a
"whenever any error continue" directive is active. Is that what is meant
by stopping error logging?
--
_____________________________________________________________________
| Colin McGrath c...@trac3000.ueci.com |
| Raytheon Engineers & Constructors, Inc. (215) 422-4144 |
| Phila, PA, USA Standard Disclaimers Apply |
|___________________________________________________________________|
> From mar...@linux.ctonline.it Sun Feb 15 06:05:50 1998
> From: Marco Greco <mar...@linux.ctonline.it>
> To: yose...@netcom.com
> CC: inform...@iiug.org
> Subject: Re: Checking datatype of CHAR variable in 4GL
>
> That's exactly what I meant, Alan. Form errors (i.e. conversion errors, for
> instance) are logged in the error log even after a WHENEVER ANY ERROR CONTINUE,
> which obviously isn't the correct way of handling errors.
Well, "correct" is a subjective term here. The "error log" is better
considered a MESSAGE log, and the messages may or may not indicate
actual errors that need attention. The log indicates when negative
STATUS values have been encountered which, depending on program design
and need, may or may not indicate an erroneous condition.
IMHO, having more info is better than less, since you can choose to ignore
those negative STATUS values that need no action on your part. From your
perspective, perhaps this just gives you more "noise" that causes unnecessary
interrupts.
I don't know of a solution that satisfies us both here.
> To make it more clear, this is the contents of my error log after running the
> following useless program (4gl/c 4.16UC2 x SCO 3.2.5.0)
>
--
Alan Denney yose...@netcom.com
The catchall for case is "whenever else".
case myfield
when "A"
do this
whenever else
do that
end case
Ben Knox <b...@dircon.net> wrote in article
<34e2f...@newsread1.dircon.co.uk>...
> Does anyone if there a function in Informix 4gl (version 4) which will
let
> you check the contents of a CHAR variable to see whether or not it is a
> valid number, without causing a numeric conversion error?
>
> I have an application which is requesting input from the user, and the
input
> can be a number, or a string. This then gets put through a CASE
statement,
> more or less as follows:
>
> DEFINE
> var CHAR(5)
>
> PROMPT "Enter data: " FOR var
>
> CASE
>
> WHEN var>=1 AND var<=9999
> DISPLAY "Var is a number"
> WHEN var IS NOT NULL
> DISPLAY "Var is a string"
> END CASE
>
> The problem I've got is that if the user enters a string, the program
bombs
> out with a "Character to numeric conversion error" at the first WHEN
clause.
>
> Lastly, does anyone know if there is a "catchall" WHEN statement (like
the *
> in a UNIX shell CASE statement).
>
Agreed there. I think the original reasoning is that the volume of
generated code to track it would be extreme (combined with carrying that
info down all the code levels to the bottom-level conversion routines).
There are ways to narrow it down, such as logging "I'm here" messages
upon entering each module in a debug context...
> On on of our customer sites were are seeing ten's of these messages
> no idea where it came from...even a debugging enviroment variable to
> cause a core dunp would be better than nothing...
>
Whoa. These are NOT server messages -- the server will not accept
data where conversion errors occur -- so I think this particular concern
is invalid.
>>Marco
>>_______________________________________________________________________________
--
Alan Denney yosemite_at_netcom.com
"My opinions may have changed, but not the fact that I am right."
-- Ashleigh Brilliant
Oops. There I go again, assuming implemented stuff.
No, there is no official, documented shut_off_logging_dammit() function.
However, in theory, one could call a programmer-defined C function that
in turn called fgl_clog() (with no parameters) out of fgllib.
But that would be using undocumented internals. That would be dangerous.
That would be, well, just WRONG. WRONG, I tell you!
Bad programmer! B-A-D programmer!
--
Alan Denney yosemite_at_netcom.com
"I'll employ my resources to make your puny lives miserable! I'll crush your
pitiful dreams and ambitions like bugs in the dust!"
-- Calvin
>I agree with the guy who said you need to resort to C to check whether
>the field is numeric or not. If you want some example 4gl and C code on
>how to do this drop a line at tyc...@flash.net.
I missed the start of this thread, but for 4GL what about
FOR count_l = 1 TO LENGTH(char_var)
IF char_var[count_l, count_l] < "0" OR char_var[count_l, count_l] > "9" THEN
<not numeric>
END IF
END FOR
>The catchall for case is "whenever else".
>case myfield
> when "A"
> do this
> whenever else
> do that
>end case
? Again, for 4GL, isn't it OTHERWISE, as in
CASE
WHEN thing
do this
OTHERWISE
do that
END CASE
--
Bryan Tonnet
bato...@phase4.com.au
Well, my assertion of incorrectness springs from essentially two facts:
- change in behaviour across versions: WHENEVER ANY ERROR CONTINUE did *not* log
conversion errors up to and including (I think) 4.12/6.00.
- inconsistency with sql error trapping behaviour: a comparable example would be
to prompt the user for a quick sql statement, and PREPARE it with WHENEVER
ERROR CONTINUE in effect. in case of error, you are presented with a negative
status & SQLCA.SQLCODE, and nothing in the error log.
In due time I went through the release notes, and I must say I agree on the fact
that back in the old days conversion error log trapping was confusing for the
user, however I'm not sure the changes introduced go in the right direction:
nowhere in the release notes it is said that the intention was to change the
error logging behaviour described in the 4gl ref man, vol 1, chapter 2 (when
WHENEVER ERROR CONTINUE is in effect, no error is written to the error log),
plus logging conversion errors without specifing their exact location, and
without warning the user, now means that I can no longer track down conversion
errors - at least in the good old days the user would come to me and say "the
computer said this when I was doing that"!
On the other hand, it goes by itself that relying on conversion error trapping
to
check whether a string is made up by integers only is not the best of
programming
practices - ...practical, maybe, but not orthodox.
The sad note, however is that this is not the only minor behavioural change
across minor release numbers: for instance PAGE HEADER #1 processing (as opposed
to FIRST PAGE HEADER) broke some havoc, over here.
Ciao,
Marco
_______________________________________________________________________________
Marco Greco, Catania, Italy mar...@linux.ctonline.it
rem radioterapia +39 95 447828 fax 446558
Informix faq http://www.iiug.org/techinfo/faq/informix.htm
4glworks http://www.ctonline.it/~marcog
Informix on Linux http://www.ctonline.it/~marcog/ifmxlinux.htm
Alan Denney wrote:
>
> > From mar...@linux.ctonline.it Sun Feb 15 06:05:50 1998
> > From: Marco Greco <mar...@linux.ctonline.it>
> > To: yose...@netcom.com
> > CC: inform...@iiug.org
> > Subject: Re: Checking datatype of CHAR variable in 4GL
> >
> > That's exactly what I meant, Alan. Form errors (i.e. conversion errors, for
> > instance) are logged in the error log even after a WHENEVER ANY ERROR CONTINUE,
> > which obviously isn't the correct way of handling errors.
>
> Well, "correct" is a subjective term here. The "error log" is better
> considered a MESSAGE log, and the messages may or may not indicate
> actual errors that need attention. The log indicates when negative
> STATUS values have been encountered which, depending on program design
> and need, may or may not indicate an erroneous condition.
>
> IMHO, having more info is better than less, since you can choose to ignore
> those negative STATUS values that need no action on your part. From your
> perspective, perhaps this just gives you more "noise" that causes unnecessary
> interrupts.
>
> I don't know of a solution that satisfies us both here.
>
> > To make it more clear, this is the contents of my error log after running the
> > following useless program (4gl/c 4.16UC2 x SCO 3.2.5.0)
> >
>
Right, largely because conversion error handling in general was (IMHO) broken
and inconsistent in the first place. This brings us back to the days where
RDS did one thing and compiled 4GL did another. The concept of uniform
Error Scope (and the "AnyError" vs "Normal" terminology I invented to
distinguish traditional c4gl methodology from the better, more thorough
RDS methodology) came in with 4.12/6.00. This cleanup helped 4GL programmers
take better advantage of considerable internal cleanups that Jonathan performed
for 4.12. (See $INFORMIXDIR/release/TOOLREL_4.1 under "CHANGES TO 4GL ERROR
HANDLING" for the release note I wrote on the topic... it was later folded
into the 4.1 and 6.0 4GL Supplement manuals, 1996 editions).
Honestly: did anybody out there PREFER the OLD way to the post-4.12 way?
Recall what that really meant for conversion errors: at the time of the
error, the conversion error message was just dumped to stdout/stderr with
no context whatsoever!
>- inconsistency with sql error trapping behaviour: a comparable example would be
> to prompt the user for a quick sql statement, and PREPARE it with WHENEVER
> ERROR CONTINUE in effect. in case of error, you are presented with a negative
> status & SQLCA.SQLCODE, and nothing in the error log.
I'll agree that this should be programmer-selectable... but the behavior
is as documented under the startlog() function documentation.
>In due time I went through the release notes, and I must say I agree on the fact
>that back in the old days conversion error log trapping was confusing for the
>user, however I'm not sure the changes introduced go in the right direction:
>nowhere in the release notes it is said that the intention was to change the
>error logging behaviour described in the 4gl ref man, vol 1, chapter 2 (when
>WHENEVER ERROR CONTINUE is in effect, no error is written to the error log),
>plus logging conversion errors without specifing their exact location, and
>without warning the user, now means that I can no longer track down conversion
>errors - at least in the good old days the user would come to me and say "the
>computer said this when I was doing that"!
To the best of my recollection, conversion errors were never given context
information in the prior releases either...
>The sad note, however is that this is not the only minor behavioural change
>across minor release numbers: for instance PAGE HEADER #1 processing (as opposed
>to FIRST PAGE HEADER) broke some havoc, over here.
Not sure what you mean here... Ace and 4GL reports control-break logic were
badly broken in the old days; it took me four years of heavy lobbying to
get Product Mgmt at the time to agree. (It used to be that the report writers
would trigger a new page as soon as the existing page was filled, rather than
waiting until the next page was actually necessary. This had UGLY
side-effects, including erroneous group info if you printed group-specific
data in a PAGE HEADER).
--
Alan Denney yosemite_at_netcom.com
"San Francisco politics are interesting in the sense that zoo animals
are interesting." -- Duane Garrett (1946-1995)
I have to agree with Marco here and I don't know why this should be
programmer selectable. Consider the following:
1. With "whenever any error continue" the programmer has decided to trap
error-codes himself. Conversion error-codes don't automatically crash
the program and, reasonably, shouldn't automatically log to the error
log. If the program is handling the error-code it can decide whether to
log an error message.
2. The manuals effectively say that within a "whenever error continue"
block, SQL error-codes aren't logged. While nothing is specifically said
about the "whenever any error" statement, reason says it should be
consistent with "whenever error". SQL error-codes are sometimes normal
and so are conversion error-codes.
3. I can't imagine anyone being interested in a log file growing at a
mad rate describing conversion error-codes that were handled by the
program. To say that the error log isn't really an error log but a
message log is kind of circumventing the issue.
I do agree that the newer error handling methods in 4gl are an
improvement. It would even be better with this seemingly minor
adjustment of not logging errors that weren't errors.
Best wishes,
----------------------------------------------------------------------
John H. Frantz Power-4gl: Extending Informix-4gl
jo...@rl.is http://www.rl.is/~john/pow4gl.html
I disagree.
First of all, by using AnyError scope (as opposed to plain old WHENEVER ERROR,
you use WHENEVER ANY ERROR), you are saying you WANT to know about all
abnormal conditions... for which you are free to choose your own handling,
or no handling.
Second of all, aside from bugs, [-: no error code "automatically crashes
a program". Many errors would have you wanting to keep the program going,
if for no other reason than to dump diagnostic info, rollback partial
work, inform the user, set resumption points, or whatever...
>2. The manuals effectively say that within a "whenever error continue"
>block, SQL error-codes aren't logged. While nothing is specifically said
>about the "whenever any error" statement, reason says it should be
>consistent with "whenever error". SQL error-codes are sometimes normal
>and so are conversion error-codes.
I missed that part...
>3. I can't imagine anyone being interested in a log file growing at a
>mad rate describing conversion error-codes that were handled by the
>program. To say that the error log isn't really an error log but a
>message log is kind of circumventing the issue.
My point is, that conversion errors are rarely expected behavior, unless
validating user input or doing date arithmetic with year-month intervals.
If conversion errors are rampant in any program *I'm* responsible for,
I want to know where they're coming from.
>I do agree that the newer error handling methods in 4gl are an
>improvement. It would even be better with this seemingly minor
>adjustment of not logging errors that weren't errors.
Agreed. I'd also like to research why module/line info isn't coming across
(perhaps Jonathan remembers). The error routines will provide it if its
available; it's not "bubbling up" for those cases... my guess is that
it's due to use of internal-standard conversion routines that aren't designed
to pass upward toos-specific info. (And keep in mind that if 4GL were changed
to provide such infrastructure, there could be performance penalties to
existing programs...)
>John H. Frantz Power-4gl: Extending Informix-4gl
>jo...@rl.is http://www.rl.is/~john/pow4gl.html
--
Alan Denney yosemite_at_netcom.com
Look for me on the California Attorney General's Tamagotchi-abuser CD-ROM.
What I don't like about this approach is that it is time consuming.
Anytime you ask 4gl to wander through a string you're wasting time. Not a
big deal when you're talking onsey-twosey, but when this is a core
algorithm for thousands or millions of records/rows it can get quite
expensive. Much better to call a 'c' routine in these cases.
cheers
j.
bato...@zeta.org.au (Bryan Tonnet) on 02/19/98 12:19:20 AM
Please respond to bato...@zeta.org.au (Bryan Tonnet)
To: inform...@iiug.org
cc: (bcc: Jack Parker/Boston50/Epsilon)
Subject: Re: Checking datatype of CHAR variable in 4GL
jpa...@epsilon.com wrote:
> What I don't like about this approach is that it is time consuming.
> Anytime you ask 4gl to wander through a string you're wasting time. Not a
> big deal when you're talking onsey-twosey, but when this is a core
> algorithm for thousands or millions of records/rows it can get quite
> expensive. Much better to call a 'c' routine in these cases.
>
> cheers
> j.
Sigh,
Try this.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctypes.h>
/* If not already defined */
#define TRUE 1
#define FALSE 0
int is_num( char *string)
{
char *ptr;
int flag, len;
flag = TRUE;
ptr = string;
len = strlen(string);
while ( flag && len) {
if ( (isdigit(*ptr) == 0))
flag = FALSE;
ptr++;
len -= 1;
}
return (flag);
}
Caveats:
I wrote it so use it at your own peril!
This was written on the fly and hasn't been tested. In other words, it aint
kosher!
So play with this code.