1 |
;+ |
2 |
; NAME: |
3 |
; VALID_NUM |
4 |
; PURPOSE: |
5 |
; Check if a string is a valid number representation. |
6 |
; EXPLANATION: |
7 |
; The input string is parsed for characters that may possibly |
8 |
; form a valid number. It is more robust than simply checking |
9 |
; for an IDL conversion error because that allows strings such |
10 |
; as '22.3qwert' to be returned as the valid number 22.3 |
11 |
; See also the original NUM_CHK which returns the status in |
12 |
; the opposite sense. |
13 |
; |
14 |
; CALLING SEQUENCE: |
15 |
; IDL> status = valid_num(string [,value] [,/integer]) |
16 |
; |
17 |
; Inputs : string - the string to be tested |
18 |
; |
19 |
; Opt. Inputs : None |
20 |
; |
21 |
; Outputs : The function returns 1 for valid, 0 for invalid number |
22 |
; |
23 |
; Opt. Outputs: value - The value the string decodes to. This will be |
24 |
; returned as a double precision number unless /INTEGER |
25 |
; is present, in which case a long integer is returned. |
26 |
; |
27 |
; Keywords : Integer - if present code checks specifically for an integer. |
28 |
; |
29 |
; Calls : None |
30 |
; |
31 |
; Restrictions: None |
32 |
; |
33 |
; Category : Utilities, Numerical |
34 |
; |
35 |
; Prev. Hist. : Small changes from NUM_CHK by Andrew Bowen, |
36 |
; Tessella Support Services, 8/3/93 |
37 |
; |
38 |
; Written : CDS version by C D Pike, RAL, 24-May-93 |
39 |
; |
40 |
; Modified : Version 1, C D Pike, RAL, 24-May-93 |
41 |
; Version 2, William Thompson, GSFC, 14 October 1994 |
42 |
; Added optional output parameter VALUE to allow |
43 |
; VALID_NUM to replace STRNUMBER in FITS routines. |
44 |
; |
45 |
; Version : Version 1 24-May-93 |
46 |
; Converted to IDL V5.0 W. Landsman September 1997 |
47 |
;- |
48 |
|
49 |
FUNCTION valid_num, string, value, INTEGER=integer |
50 |
|
51 |
;**** Set defaults for keyword **** |
52 |
IF NOT (KEYWORD_SET(integer)) THEN integer=0 |
53 |
|
54 |
;**** arrays of legal characters **** |
55 |
numbers = '0123456789' |
56 |
signs = '+-' |
57 |
decimal = '.' |
58 |
exponents = 'ED' |
59 |
|
60 |
;**** trim leading and trailing blanks/compress white **** |
61 |
;**** space and convert any exponents to uppercase. **** |
62 |
numstr = strupcase(strtrim(strcompress(string),2)) |
63 |
|
64 |
;**** length of input string **** |
65 |
len = strlen(numstr) |
66 |
|
67 |
ok = 1 |
68 |
|
69 |
if integer eq 0 then stage = 1 else stage = 6 |
70 |
|
71 |
for i = 0, len-1 do begin |
72 |
|
73 |
char = strmid(numstr,i,1) |
74 |
|
75 |
;**** the parsing steps 1 to 8 are for floating **** |
76 |
;**** point, steps 6 to 8, which test for a legal **** |
77 |
;**** exponent, can be used to check for integers **** |
78 |
|
79 |
;**** The parsing structure is as follows. Each character in the **** |
80 |
;**** string is checked against the valid list at the current **** |
81 |
;**** stage. If no match is found an error is reported. When a **** |
82 |
;**** match is found the stage number is updated as indicated **** |
83 |
;**** ready for the next character. The valid end points are **** |
84 |
;**** indicated in the diagram. **** |
85 |
; |
86 |
;Stage 1 2 3 4 |
87 |
; |
88 |
;Valid sign --> 2 dec-pt --> 3 digit --> 5 dec-pt --> 5 |
89 |
; " dec-pt --> 3 digit --> 4 digit --> 4 |
90 |
; " digit --> 4 exp't --> 6 |
91 |
; " END |
92 |
; |
93 |
;Stage 5 6 7 8 |
94 |
; |
95 |
;Valid digit --> 5 sign --> 7 digit --> 8 digit -->8 |
96 |
; " exp't --> 6 digit --> 8 END |
97 |
; " END |
98 |
; |
99 |
|
100 |
CASE stage OF |
101 |
|
102 |
1 : begin |
103 |
if strpos(signs,char) ge 0 then stage = 2 $ |
104 |
else if decimal eq char then stage = 3 $ |
105 |
else if strpos(numbers,char) ge 0 then stage = 4 $ |
106 |
else ok = 0 |
107 |
end |
108 |
|
109 |
2 : begin |
110 |
if decimal eq char then stage = 3 $ |
111 |
else if strpos(numbers,char) ge 0 then stage = 4 $ |
112 |
else ok = 0 |
113 |
end |
114 |
|
115 |
3 : begin |
116 |
if strpos(numbers,char) ge 0 then stage = 5 $ |
117 |
else ok = 0 |
118 |
end |
119 |
|
120 |
4 : begin |
121 |
if decimal eq char then stage = 5 $ |
122 |
else if strpos(numbers,char) ge 0 then stage = 4 $ |
123 |
else if strpos(exponents,char) ge 0 then stage = 6 $ |
124 |
else ok = 0 |
125 |
end |
126 |
|
127 |
5 : begin |
128 |
if strpos(numbers,char) ge 0 then stage = 5 $ |
129 |
else if strpos(exponents,char) ge 0 then stage = 6 $ |
130 |
else ok = 0 |
131 |
end |
132 |
|
133 |
6 : begin |
134 |
if strpos(signs,char) ge 0 then stage = 7 $ |
135 |
else if strpos(numbers,char) ge 0 then stage = 8 $ |
136 |
else ok = 0 |
137 |
end |
138 |
|
139 |
7 : begin |
140 |
if strpos(numbers,char) ge 0 then stage = 8 $ |
141 |
else ok = 0 |
142 |
end |
143 |
|
144 |
8 : begin |
145 |
if strpos(numbers,char) ge 0 then stage = 8 $ |
146 |
else ok = 0 |
147 |
end |
148 |
|
149 |
ENDCASE |
150 |
|
151 |
end |
152 |
|
153 |
;**** check that the string terminated legally **** |
154 |
;**** i.e in stages 4, 5 or 8 **** |
155 |
if (stage ne 4) and (stage ne 5) and (stage ne 8) then ok = 0 |
156 |
|
157 |
;**** If requested, then form the value. **** |
158 |
|
159 |
if (n_params() eq 2) and ok then begin |
160 |
if keyword_set(integer) then value = long(string) else $ |
161 |
value = double(string) |
162 |
endif |
163 |
|
164 |
;**** return error status to the caller **** |
165 |
RETURN, ok |
166 |
|
167 |
|
168 |
END |