File: UTILS\U_VALUES.CPP
1 //#############################################################################
2 // //
3 // U_VALUES.CPP //
4 // Subsystem: Utilities - Tools für Zahlen und Strings //
5 // Deklaration: U_VALUES.H //
6 //---------------------------------------------------------------------------//
7 // Autoren: Thomas Kullmann, Günther Reinecker //
8 // Stand: 07.11.2002 //
9 // //
10 //#############################################################################
11
12 #include <stdio.h> // sprintf
13 #include <string.h> // strlen, strcpy
14 #include <math.h> // pow, ceil, floor
15 #include <stdlib.h> // für variable Parameteranzahl
16 #include <stdarg.h>
17
18 #include "utils\u_values.h" // SCHNITTSTELLE für diese Datei
19 #include "utils\u_window.h" // MBINFO
20
21 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
22
23
24 #ifdef _DEBUG
26 #endif
27
28 ////////////////////////////////////////////////////////////////////////////////
29 // Trace
30 ////////////////////////////////////////////////////////////////////////////////
31
32 void _CURVECLASS WINAPI TraceMsg ( LPCSTR aStr )
33 {
34 MessageBox( NULL, aStr, "Trace", MBINFO );
35 }
36
37 void _CURVECLASS WINAPI TraceMsg ( const double aDouble )
38 {
39
40 char buf[ _MAXLENDOUBLE + 1 ]; // + Nullterminierung
41 sprintf( buf, "%.10f", aDouble );
42 TraceMsg(buf);
43 }
44
45 void _CURVECLASS WINAPI Trace ( LPCSTR aStr )
46 {
47 #ifdef _DEBUG
53 #endif // _DEBUG
54 }
55
56 void _CURVECLASS WINAPI TraceErr ( LPCSTR aStr )
57 {
58 #ifdef _DEBUG
64 #endif // _DEBUG
65 }
66
67 void _CURVECLASS WINAPI Trace ( const double aDouble )
68 {
69 #ifdef _DEBUG
73 #endif // _DEBUG
74 }
75
76 ////////////////////////////////////////////////////////////////////////////////
77 // Runden, Abrunden von Double-Werten
78 ////////////////////////////////////////////////////////////////////////////////
79
80 double _CURVECLASS WINAPI DoubleRound ( const double aDouble, const UINT aDigits )
81 {
82 if ( aDouble < 0 )
83 return DoubleRoundOff( aDouble - 0.5, aDigits );
84 else
85 return DoubleRoundOff( aDouble + 0.5, aDigits );
86 }
87 //-----------------------------------------------------------------------------
88
89 double _CURVECLASS WINAPI DoubleRoundUp ( const double aDouble, const UINT aDigits )
90 {
91 double corfak= pow( 10, aDigits ); //Multiplikation mit diesem Wert verschiebt das Komma nach rechts, Division nach links
92 double temp= aDouble*corfak;
93 double temp2= DoubleRoundOff(temp, 0);
94 //Aufrunden durch Überprüfung der Nachkommastelle
95 if ( aDouble < 0 ) {
96 if ( temp2-temp>=0.09 ) temp2++;
97 } else {
98 if ( temp-temp2>=0.09 ) temp2++;
99 }
100 //Komma zurück an seine ursprüngliche Position
101 return temp2 / corfak;
102 }
103 //-----------------------------------------------------------------------------
104
105 double _CURVECLASS WINAPI DoubleRoundOff ( const double aDouble, const UINT aDigits )
106 {
107 double temp, corfak= pow( 10, aDigits ); //Multiplikation mit diesem Wert verschiebt das Komma nach rechts, Division nach links
108 //abrunden durch Verwerfen der Nachkommastellen
109 if ( aDouble < 0 )
110 temp= ceil( aDouble * corfak );
111 else
112 temp= floor( aDouble * corfak );
113 //Komma zurück an seine ursprüngliche Position
114 return temp / corfak;
115 }
116 //-----------------------------------------------------------------------------
117
118 float _CURVECLASS WINAPI Double2Float ( const double aDouble, const UINT aDigits )
119 {
120 double temp= aDouble * pow((double)10, (double)aDigits);
121 float result= (float)temp;
122 return result / powf((float)10, (float)aDigits);
123 }
124 //-----------------------------------------------------------------------------
125
126 double _CURVECLASS WINAPI Float2Double ( const float aFloat, const UINT aDigits )
127 {
128 float temp= aFloat * powf((float)10, (float)aDigits);
129 double result= (double)temp;
130 return result / pow((double)10, (double)aDigits);
131 }
132
133 ////////////////////////////////////////////////////////////////////////////////
134 // Stringmanipulation
135 ////////////////////////////////////////////////////////////////////////////////
136
137 LPSTR _CURVECLASS WINAPI GetFormatedString( LPCSTR aFormat, ... )
138 {
139 va_list args;
140 va_start( args, aFormat );
141 char *result= GetFormatedStringMaxLen( aFormat, 256, args );
142 va_end( args );
143 return result;
144 }
145 LPSTR _CURVECLASS WINAPI GetFormatedString( LPCSTR aFormat, va_list &args )
146 {
147 return GetFormatedStringMaxLen( aFormat, 256, args );
148 }
149 //-----------------------------------------------------------------------------
150
151 LPSTR _CURVECLASS WINAPI GetFormatedStringMaxLen( LPCSTR aFormat, const UINT aMaxLen, ... )
152 {
153 va_list args;
154 va_start( args, aMaxLen );
155 char *buf= GetFormatedStringMaxLen( aFormat, aMaxLen, args );
156 va_end( args );
157 return buf;
158 }
159 LPSTR _CURVECLASS WINAPI GetFormatedStringMaxLen( LPCSTR aFormat, const UINT aMaxLen, va_list &args )
160 {
161 char *buf= 0;
162 buf= new char [ aMaxLen+1 ];
163 vsprintf( buf, aFormat, args );
164 return buf;
165 }
166
167 ////////////////////////////////////////////////////////////////////////////////
168 // Stringmanipulation und "Ist String ein Double?"
169 ////////////////////////////////////////////////////////////////////////////////
170
171 void _CURVECLASS WINAPI StringReplace ( char *aString, const char aOld, const char aNew )
172 {
173 if ( !aString )
174 return; //Leerstring, nichts zu tun
175
176 for ( UINT i= 0; i < strlen(aString); i++ )
177 if ( aString[i] == aOld )
178 aString[i]= aNew;
179 }
180 //-----------------------------------------------------------------------------
181
182 void _CURVECLASS WINAPI StringIgnore ( char *aString, const char aIgnore )
183 {
184 if ( !aString || aIgnore=='\0' )
185 return; // Leerstring oder zu ignorierendes Zeichen ist Nullterminierung: nichts zu tun
186
187 for ( UINT i= 0; i < strlen(aString); )
188 if ( aString[i] == aIgnore ) {
189 for ( UINT j= i+1; j < strlen(aString); j++ )
190 aString[j-1]= aString[j];
191 aString[strlen(aString)-1]= '\0';
192 // i nicht erhoehen, Stelle <i> nochmal prüfen, wurde ja geändert
193 } else i++;
194 }
195 //-----------------------------------------------------------------------------
196
197 int _CURVECLASS WINAPI DoubleErr ( LPCSTR aString, const char aDecimal, const char aThousand )
198 {
199 if ( (!aString) || (strlen(aString)==0) )
200 return 1; //Leerstring ist kein Double
201
202 char *temp= new char[strlen(aString)+1]; // + Nullterminierung
203 strcpy(temp, aString);
204 if ( aThousand!='\0' ) StringIgnore( temp, aThousand );
205
206 BOOL foundDecimal= FALSE;
207 for ( UINT i= 0; i < strlen(temp); i++ )
208 {
209 if ( temp[i] == aDecimal )
210 {
211 if ( foundDecimal )
212 return i; //zu viele Kommata
213 else
214 foundDecimal= TRUE;
215 }
216 else if ( temp[i] == '-' )
217 {
218 if ( i > 0 )
219 return i; //ungültiges Minuszeichen
220 }
221 else if ( (temp[i] == '0') || (temp[i] == '1') || (temp[i] == '2') || (temp[i] == '3') || (temp[i] == '4') ||
222 (temp[i] == '5') || (temp[i] == '6') || (temp[i] == '7') || (temp[i] == '8') || (temp[i] == '9') )
223 {
224 //darf überall stehen
225 }
226 else
227 return i; //ungültiges Zeichen
228 }
229 return -1;
230 }
231 //-----------------------------------------------------------------------------
232
233 BOOL _CURVECLASS WINAPI IsDouble ( LPCSTR aString, const char aDecimal, const char aThousand )
234 {
235 return ( DoubleErr( aString, aDecimal, aThousand ) == -1 ); //keine fehlerhafte Stelle
236 }
237
238 ////////////////////////////////////////////////////////////////////////////////
239 // Konvertierung zwischen String und Double
240 ////////////////////////////////////////////////////////////////////////////////
241
242 double _CURVECLASS WINAPI String2Double ( LPCSTR aString, const UINT aDigits, const BOOL aRound, const char aDecimal, const char aThousand )
243 {
244 char *temp= new char[ strlen(aString) + 2 ]; // + Nullterminierung und neue "0" vor dem Komma
245 strcpy( temp, aString );
246 StringReplace( temp, aDecimal, '.' );
247 if ( aThousand!='\0' ) StringIgnore( temp, aThousand );
248 double aResult= atof( temp ); //im Gegensatz zu sscanf mit Double-Genauigkeit
249 _FREELIST(temp);
250 if ( aRound )
251 return DoubleRound( aResult, aDigits );
252 else
253 return DoubleRoundOff( aResult, aDigits );
254 }
255 //-----------------------------------------------------------------------------
256
257 UINT GetDigits(const double aDouble)
258 {
259 if ( fabs(aDouble)>=100 ) return 0;
260 else if ( fabs(aDouble)>=10 ) return 1;
261 else if ( fabs(aDouble)>=1 ) return 2;
262 else if ( fabs(aDouble)>=0.5 ) return 3;
263 else if ( fabs(aDouble)>=0.25 ) return 4;
264 else return 5;
265 }
266
267 void _CURVECLASS WINAPI Double2String ( char *aReturn, const double aDouble, UINT aDigits, const BOOL aRound, const char aDecimal, const char aThousand )
268 {
269 if ( aDigits>=NKAUTO ) aDigits= GetDigits(aDouble) + (aDigits-NKAUTO);
270 double temp= aDouble;
271 if ( !aRound )
272 temp= DoubleRoundOff( aDouble, aDigits ); //sprintf rundet automatisch
273 //in String konvertieren
274 char format[6];
275 sprintf( format, "%%.%df", aDigits ); //z.B. "%.3f" / "%.5f" -> Float-Werte mit drei / fünf Nachkommastellen
276 sprintf( aReturn, format, temp ); //aValue konvertiert als String (Nachkommastellengenauigkeit: <aDigits>)
277 StringReplace( aReturn, '.', aDecimal );
278 if ( aThousand!='\0' ) { // Tausenderpunkte setzen
279 // Position des Komma suchen (wenn keines, Ende der Zeichenkette nehmen)
280 bool foundDecimal= false;
281 UINT decimal= 0;
282 for (UINT i= 0; i<strlen(aReturn); i++) if ( aReturn[i]==aDecimal ) {
283 decimal= i;
284 foundDecimal= true;
285 break;
286 }
287 if ( !foundDecimal ) decimal= strlen(aReturn); // wenn kein Komma, letzte Position nehmen
288
289 // Tausendertrennzeichen einfügen
290 i= decimal;
291 while (i>=0) {
292 if ( aReturn[i]=='-' ) {
293 break;
294 } else if ( decimal-i==3 && i>0 && aReturn[i-1]!='-' ) { // Tausendertrennzeichen soll gesetzt werden (aber nicht direkt vor einem Minus!)
295 aReturn[strlen(aReturn)+1]= '\0';
296 for ( UINT j= strlen(aReturn); j>=i; j-- ) aReturn[j+1]= aReturn[j];
297 aReturn[i]= aThousand;
298 decimal= i; // so behandeln, als ob hier ein Komma steht; dann können wir einfach mit konstantem Anstand von 3 rechnen
299 }
300 if ( i>0 ) i--;
301 else break;
302 }
303 }
304 }
305 ////////////////////////////////////////////////////////////////////////////////
306 // Formatierte Zeitausgabe
307 ////////////////////////////////////////////////////////////////////////////////
308
309 void _CURVECLASS WINAPI GetTimeString( char *aReturn, long aMillSec )
310 {
311 sprintf( (LPSTR)aReturn, "%02d:%02d:%02d", (int)(aMillSec / 3600000l), (int)(aMillSec / 60000l) % 60, (int)(aMillSec / 1000l) % 60 );
312 }
313
314 //Datum: 16.08.2002
315 ////////////////////////////////////////////////////////////////////////////////
316 // Min, Max
317 ////////////////////////////////////////////////////////////////////////////////
318
319 BOOL _CURVECLASS WINAPI SetInRange( double &aValue, double aBorder1, double aBorder2 )
320 {
321 if ( aBorder1 < aBorder2 )
322 {
323 if ( aValue < aBorder1 )
324 {
325 aValue= aBorder1;
326 return FALSE;
327 };
328 if ( aValue > aBorder2 )
329 {
330 aValue= aBorder2;
331 return FALSE;
332 };
333 }
334 else
335 {
336 if ( aValue > aBorder1 )
337 {
338 aValue= aBorder1;
339 return FALSE;
340 };
341 if (aValue < aBorder2)
342 {
343 aValue= aBorder2;
344 return FALSE;
345 };
346 };
347 return TRUE;
348 }
349 //-----------------------------------------------------------------------------
350
351 BOOL _CURVECLASS WINAPI SetInRange( long &aValue, long aBorder1, long aBorder2 )
352 {
353 if ( aBorder1 < aBorder2 )
354 {
355 if ( aValue < aBorder1 )
356 {
357 aValue= aBorder1;
358 return FALSE;
359 };
360 if ( aValue > aBorder2 )
361 {
362 aValue= aBorder2;
363 return FALSE;
364 };
365 }
366 else
367 {
368 if ( aValue > aBorder1 )
369 {
370 aValue= aBorder1;
371 return FALSE;
372 };
373 if (aValue < aBorder2)
374 {
375 aValue= aBorder2;
376 return FALSE;
377 };
378 };
379 return TRUE;
380 }
381
382 /*
383 int _CURVECLASS WINAPI maxi(int value1, int value2) {
384 return ( (value1 > value2) ? value1 : value2);
385 };
386
387 int _CURVECLASS WINAPI mini(int value1, int value2) {
388 return ( (value1 < value2) ? value1 : value2);
389 };
390
391 long _CURVECLASS WINAPI maxl(long value1, long value2) {
392 return ( (value1 > value2) ? value1 : value2);
393 };
394
395 long _CURVECLASS WINAPI minl(long value1, long value2) {
396 return ( (value1 < value2) ? value1 : value2);
397 };
398
399 float _CURVECLASS WINAPI maxf(float value1, float value2) {
400 return ( (value1 > value2) ? value1 : value2);
401 };
402
403 float _CURVECLASS WINAPI minf(float value1, float value2) {
404 return ( (value1 < value2) ? value1 : value2);
405 };
406
407 double _CURVECLASS WINAPI maxd(double value1, double value2) {
408 return ( (value1 > value2) ? value1 : value2);
409 };
410
411 double _CURVECLASS WINAPI mind(double value1, double value2) {
412 return ( (value1 < value2) ? value1 : value2);
413 };*/
414