Changeset 2551 in Sophya for trunk/SophyaExt/XephemAstroLib/formats.c
- Timestamp:
- Jun 15, 2004, 6:54:12 PM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/SophyaExt/XephemAstroLib/formats.c
r1719 r2551 5 5 #include <string.h> 6 6 7 #include "P_.h"8 7 #include "astro.h" 9 8 #include "preferences.h" … … 17 16 * 600: <w>:mm.m 18 17 * 60: <w>:mm 19 */ 20 void 21 fs_sexa (out, a, w, fracbase) 22 char *out; 23 double a; 24 int w; 25 int fracbase; 26 { 18 * return number of characters written to out, not counting final '\0'. 19 */ 20 int 21 fs_sexa (char *out, double a, int w, int fracbase) 22 { 23 char *out0 = out; 27 24 unsigned long n; 28 25 int d; … … 44 41 /* form the whole part; "negative 0" is a special case */ 45 42 if (isneg && d == 0) 46 (void)sprintf (out, "%*s-0", w-2, "");43 out += sprintf (out, "%*s-0", w-2, ""); 47 44 else 48 (void) sprintf (out, "%*d", w, isneg ? -d : d); 49 out += w; 45 out += sprintf (out, "%*d", w, isneg ? -d : d); 50 46 51 47 /* do the rest */ … … 53 49 case 60: /* dd:mm */ 54 50 m = f/(fracbase/60); 55 (void)sprintf (out, ":%02d", m);51 out += sprintf (out, ":%02d", m); 56 52 break; 57 53 case 600: /* dd:mm.m */ 58 (void)sprintf (out, ":%02d.%1d", f/10, f%10);54 out += sprintf (out, ":%02d.%1d", f/10, f%10); 59 55 break; 60 56 case 3600: /* dd:mm:ss */ 61 57 m = f/(fracbase/60); 62 58 s = f%(fracbase/60); 63 (void)sprintf (out, ":%02d:%02d", m, s);59 out += sprintf (out, ":%02d:%02d", m, s); 64 60 break; 65 61 case 36000: /* dd:mm:ss.s*/ 66 62 m = f/(fracbase/60); 67 63 s = f%(fracbase/60); 68 (void)sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);64 out += sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10); 69 65 break; 70 66 case 360000: /* dd:mm:ss.ss */ 71 67 m = f/(fracbase/60); 72 68 s = f%(fracbase/60); 73 (void)sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);69 out += sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100); 74 70 break; 75 71 default: 76 72 printf ("fs_sexa: unknown fracbase: %d\n", fracbase); 77 exit(1);73 abort(); 78 74 } 75 76 return (out - out0); 79 77 } 80 78 81 79 /* put the given modified Julian date, jd, in out[] according to preference 82 80 * format. 83 */ 84 void 85 fs_date (out, jd) 86 char out[]; 87 double jd; 81 * return number of characters written to out, not counting final '\0'. 82 */ 83 int 84 fs_date (char out[], double jd) 88 85 { 89 86 int p = pref_get (PREF_DATE_FORMAT); 87 char *out0 = out; 90 88 int m, y; 91 89 double d; … … 100 98 switch (p) { 101 99 case PREF_YMD: 102 (void)sprintf (out, "%4d/%02d/%02.6g", y, m, d);100 out += sprintf (out, "%4d/%02d/%02.6g", y, m, d); 103 101 break; 104 102 case PREF_DMY: 105 (void)sprintf (out, "%2.6g/%02d/%-4d", d, m, y);103 out += sprintf (out, "%2.6g/%02d/%-4d", d, m, y); 106 104 break; 107 105 case PREF_MDY: 108 (void)sprintf (out, "%2d/%02.6g/%-4d", m, d, y);106 out += sprintf (out, "%2d/%02.6g/%-4d", m, d, y); 109 107 break; 110 108 default: 111 109 printf ("fs_date: bad date pref: %d\n", p); 112 exit (1);110 abort(); 113 111 } 114 } 115 116 /* scan a sexagesimal string and update a double. the string is of the form 117 * H:M:S. a negative value may be indicated by a '-' char before any 118 * component. All components may be integral or real. In addition to ':' the 119 * separator may also be '/' or ';' or ',' or '-'. 120 * any components not specified in bp[] are copied from old's. 121 * eg: ::10 only changes S 122 * 10 only changes H 123 * 10:0 changes H and M 124 */ 125 void 126 f_scansex (o, bp, np) 127 double o; /* old value */ 128 char bp[]; /* input string */ 129 double *np; /* new value */ 130 { 131 double oh, om, os; 132 double nh, nm, ns; 133 int nneg; 134 double tmp; 135 char c; 136 137 /* fast macro to scan each segment of bp */ 138 #define SCANSEX(new,old) \ 139 if (*bp == '-') {nneg = 1; bp++;} \ 140 if (sscanf (bp, "%lf", &new) != 1) new = old; \ 141 while ((c=(*bp)) != '\0') { \ 142 bp++; \ 143 if (c==':' || c=='/' || c==';' || c==',' || c=='-') \ 144 break; \ 145 } 146 147 /* get h:m:s components of o in case bp[] defers. 148 * and constrain to positive for now. 149 */ 150 if (o < 0.0) 151 o = -o; 152 oh = floor(o); 153 tmp = (o - oh)*60.0; 154 om = floor(tmp); 155 os = (tmp - om)*60.0; 156 157 /* round to small portion of a second to reduce differencing errors. */ 158 if (os > 59.99999) { 159 os = 0.0; 160 if ((om += 1.0) >= 60.0) { 161 om = 0.0; 162 oh += 1.0; 163 } 164 } 165 166 /* scan each component of the buffer */ 167 while (*bp == ' ') bp++; 168 nneg = 0; 169 SCANSEX (nh, oh) 170 SCANSEX (nm, om) 171 SCANSEX (ns, os) 172 173 /* back to hours */ 174 tmp = ns/3600.0 + nm/60.0 + nh; 175 if (nneg) 176 tmp = -tmp; 177 178 *np = tmp; 112 113 return (out - out0); 114 } 115 116 117 /* convert sexagesimal string str AxBxC to double. 118 * x can be anything non-numeric. Any missing A, B or C will be assumed 0. 119 * optional - and + can be anywhere. 120 * return 0 if ok, -1 if can't find a thing. 121 */ 122 int 123 f_scansexa ( 124 const char *str0, /* input string */ 125 double *dp) /* cracked value, if return 0 */ 126 { 127 double a = 0, b = 0, c = 0; 128 char str[128]; 129 char *neg; 130 int r; 131 132 /* copy str0 so we can play with it */ 133 strncpy (str, str0, sizeof(str)-1); 134 str[sizeof(str)-1] = '\0'; 135 136 neg = strchr(str, '-'); 137 if (neg) 138 *neg = ' '; 139 r = sscanf (str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c); 140 if (r < 1) 141 return (-1); 142 *dp = a + b/60 + c/3600; 143 if (neg) 144 *dp *= -1; 145 return (0); 179 146 } 180 147 … … 182 149 * PREF_DATE_FORMAT preference into its components. allow the day to be a 183 150 * floating point number, 184 * a lone component is always a year if it contains a decimal point or pref 185 * is MDY or DMY and it is not a reasonable month or day value, respectively. 186 * leave any unspecified component unchanged. 187 * actually, the slashes may be anything but digits or a decimal point. 151 * actually the slashes may be anything but digits. 152 * a lone component with a decimal point is considered a year. 188 153 */ 189 154 void 190 f_sscandate (bp, pref, m, d, y) 191 char *bp; 192 int pref; /* one of PREF_X for PREF_DATE_FORMAT */ 193 int *m, *y; 194 double *d; 195 { 196 double comp[3]; /* the three components */ 197 int set[3]; /* set[i] is 1 if component i is present */ 198 int in; /* scan state: 1 while we are in a component */ 199 int ncomp; /* incremented as each component is discovered */ 200 int ndp; /* number of decimal points in last component */ 201 char *bp0 = NULL, c; 202 203 set[0] = set[1] = set[2] = 0; 204 ncomp = 0; 205 in = 0; 206 ndp = 0; 207 208 /* scan the input string. 209 * '\0' counts as a component terminator too. 210 */ 211 do { 212 /* here, *bp is the next character to be investigated */ 213 c = *bp; 214 if (c == '.' || isdigit(c) || (c == '-' && !in)) { 215 /* found what passes for a floating point number */ 216 if (in == 0) { 217 /* save the beginning of it in bp0 and init ndp */ 218 bp0 = bp; 219 in = 1; 220 ndp = 0; 221 } 222 if (c == '.') 223 ndp++; 224 } else if (c != ' ') { 225 /* not in a number now ... */ 226 if (in) { 227 /* ... but we *were* in a number, so it counts */ 228 if (ncomp >= 3) 229 return; /* too many components.. just bail */ 230 comp[ncomp] = atod (bp0); 231 set[ncomp] = 1; 232 in = 0; 233 } 234 235 /* regardless, a non-blank non-float means another component */ 236 ncomp++; 155 f_sscandate ( 156 char *bp, 157 int pref, /* one of PREF_X for PREF_DATE_FORMAT */ 158 int *m, 159 double *d, 160 int *y) 161 { 162 double c[3]; /* the three components */ 163 int n; 164 165 memset (c, 0, sizeof(c)); 166 n = sscanf (bp, "%lf%*[^0-9]%lf%*[^0-9]%lf", &c[0], &c[1], &c[2]); 167 if (n == 1 && (strchr(bp, '.') 168 || (pref == PREF_MDY && (c[0] < 1 || c[0] > 12)) 169 || (pref == PREF_DMY && (c[0] < 1 || c[0] > 31)))) { 170 double Mjd; 171 year_mjd (c[0], &Mjd); 172 mjd_cal (Mjd, m, d, y); 173 } else { 174 switch (pref) { 175 case PREF_MDY: 176 if (n > 0 && c[0] != 0) 177 *m = (int)c[0]; 178 if (n > 1 && c[1] != 0) 179 *d = c[1]; 180 if (n > 2 && c[2] != 0) 181 *y = (int)c[2]; 182 break; 183 case PREF_YMD: 184 if (n > 0 && c[0] != 0) 185 *y = (int)c[0]; 186 if (n > 1 && c[1] != 0) 187 *m = (int)c[1]; 188 if (n > 2 && c[2] != 0) 189 *d = c[2]; 190 break; 191 case PREF_DMY: 192 if (n > 1 && c[0] != 0) 193 *d = c[0]; 194 if (n > 2 && c[1] != 0) 195 *m = (int)c[1]; 196 if (n > 3 && c[2] != 0) 197 *y = (int)c[2]; 198 break; 237 199 } 238 bp++;239 } while (c);240 241 /* it's a decimal year if there is exactly one component and242 * it contains a decimal point243 * or we are in MDY format and it's not in the range 1..12244 * or we are in DMY format and it's not int the rangle 1..31245 */246 if (ncomp == 1 &&247 (ndp > 0248 || (pref == PREF_MDY && !(comp[0] >= 1 && comp[0] <= 12))249 || (pref == PREF_DMY && !(comp[0] >= 1 && comp[0] <= 31)))) {250 double Mjd;251 year_mjd (comp[0], &Mjd);252 mjd_cal (Mjd, m, d, y);253 return;254 200 } 255 256 switch (pref) {257 case PREF_MDY:258 if (set[0]) *m = (int)comp[0];259 if (set[1]) *d = comp[1];260 if (set[2]) *y = (int)comp[2];261 break;262 case PREF_YMD:263 if (set[0]) *y = (int)comp[0];264 if (set[1]) *m = (int)comp[1];265 if (set[2]) *d = comp[2];266 break;267 case PREF_DMY:268 if (set[0]) *d = comp[0];269 if (set[1]) *m = (int)comp[1];270 if (set[2]) *y = (int)comp[2];271 break;272 }273 }274 275 /* given a string of the form xx:mm[:ss] or xx:mm.dd, convert it to a double at276 * *dp. actually, ':' may also be ';', '/' or ',' too. all components may be277 * floats.278 * return -1 if trouble, else 0279 */280 int281 scansex (str, dp)282 char *str;283 double *dp;284 {285 double x, m = 0.0, s = 0.0;286 int isneg;287 int nf;288 289 while (isspace(*str))290 str++;291 if (*str == '-') {292 isneg = 1;293 str++;294 } else295 isneg = 0;296 297 nf = sscanf (str, "%lf%*[:;/,]%lf%*[:;/,]%lf", &x, &m, &s);298 if (nf < 1)299 return (-1);300 *dp = x + m/60.0 + s/3600.0;301 if (isneg)302 *dp = - *dp;303 return (0);304 201 } 305 202 306 203 /* For RCS Only -- Do Not Edit */ 307 static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: formats.c,v $ $Date: 200 1-10-22 12:08:27 $ $Revision: 1.2$ $Name: not supported by cvs2svn $"};204 static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: formats.c,v $ $Date: 2004-06-15 16:52:38 $ $Revision: 1.3 $ $Name: not supported by cvs2svn $"};
Note:
See TracChangeset
for help on using the changeset viewer.