Rev 12199 | Rev 13932 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3519 | schaersvoo | 1 | /* |
2 | ********************************************************************************* |
||
12199 | schaersvoo | 3 | * J.M. Evers 2/2012 * |
3519 | schaersvoo | 4 | * This is all amateur scriblings... So no copyrights. * |
5 | * This source code file, and compiled objects derived from it, * |
||
6 | * can be used and distributed without restriction, including for commercial use * |
||
5416 | schaersvoo | 7 | * No warrenty whatsoever * |
3519 | schaersvoo | 8 | ********************************************************************************* |
5416 | schaersvoo | 9 | |
12199 | schaersvoo | 10 | general use: |
11 | moneyprint number1,number2,number3... DECIMALS |
||
12 | default rounding to 2 decimals (financial math) |
||
13 | |||
14 | tot=!exec moneyprint 6.14512 --> 6.15 |
||
15 | tot=!exec moneyprint 6.14512 3 --> 6.145 |
||
16 | tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0.10,17.00,123.40,124.00 |
||
17 | tot=!exec moneyprint 2*10^7,2E-7 --> 2.00*10^7,2.00*10^-7 |
||
18 | !set use_comma |
||
19 | # only for representation ,the outcome can not be used for further arithmetics/calculations |
||
20 | tot=!exec moneyprint 6.14512 --> 6,15 |
||
21 | tot=!exec moneyprint 6.14512 3 --> 6,145 |
||
22 | tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0,10 17,00 123,40 124,00 |
||
23 | tot=!exec moneyprint 2*10^7,2E-7 --> 2,00*10^7 2,00*10^-7 |
||
24 | |||
25 | bugs & flaws: no calculations are performed , fractions are not supported |
||
26 | |||
27 | CHANGELOG |
||
5154 | schaersvoo | 28 | 2/2012 |
29 | modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers |
||
5416 | schaersvoo | 30 | tot=!exec moneyprint 2.1,4.123,5 2 // 2 decimals |
31 | tot -> 2.10,4.12,5.00 |
||
32 | tot=!exec moneyprint 2.1,4.123,5 4 // 4 decimals |
||
33 | tot -> 2.1000,4.1230,5.0000 |
||
34 | tot=!exec moneyprint 2.1,4.123,5 |
||
35 | tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals |
||
5154 | schaersvoo | 36 | |
12199 | schaersvoo | 37 | 6/2012 |
5416 | schaersvoo | 38 | modified again to support rounding of scientific numbers, like |
39 | tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3 |
||
40 | tot -> 1.235e06,1.235e6,0.012e-23 |
||
41 | assumed only powers of 10 [scientific notation] |
||
42 | |||
6273 | schaersvoo | 43 | 12/2012 |
12199 | schaersvoo | 44 | Modified : using only 10^ in powers |
45 | (e+8 -> *10^8 ; e-8 -> *10^-8) |
||
46 | Extra syntax error signal (using more than 1 'e') |
||
6273 | schaersvoo | 47 | |
8346 | schaersvoo | 48 | 27/2014 |
12199 | schaersvoo | 49 | Modified avoiding truncating of numbers like 15.625 --> 16.62 |
8346 | schaersvoo | 50 | |
12199 | schaersvoo | 51 | 2/2018 |
52 | if variable "w_use_comma" is set (eg in phtml !set use_comma=1), the result is a comma 'decimal' separator: |
||
53 | moneyprint 1.2345 2 -> 1,23 |
||
54 | moneyprint 1.2345 , 2.34567 , 3.4567 , 5 2 -> 1,23 2,35 3,46 5,00 |
||
55 | (note: in this case (multiple conversions) we use 'spaces' instead of an item ',' list ) |
||
56 | This is INCOMPATIBLE with calculating software : only suitable for REPRESENTATION of (money) numbers |
||
57 | If env. variable w_use_comma is not set or not "1" , the behaviour is a number with a decimal point |
||
58 | |||
13927 | schaersvoo | 59 | 5/2019 use "strlcpy, strlcat" - size-bounded string copying and concatenation |
3519 | schaersvoo | 60 | */ |
8346 | schaersvoo | 61 | |
3519 | schaersvoo | 62 | #include <stdio.h> |
63 | #include <stdlib.h> |
||
64 | #include <string.h> |
||
8346 | schaersvoo | 65 | #include <math.h> |
12199 | schaersvoo | 66 | #include <locale.h> |
67 | |||
68 | #define MAX_DIGITS 128 |
||
5416 | schaersvoo | 69 | #define MAX_CONV 32 |
12199 | schaersvoo | 70 | #define LOCALE "fr_FR.ISO8859-1" |
3519 | schaersvoo | 71 | |
12199 | schaersvoo | 72 | |
3689 | schaersvoo | 73 | int main( int argc , char *argv[]){ |
12199 | schaersvoo | 74 | if( argc != 2 && argc != 3){ |
75 | fprintf(stdout,"error !\nusage:\n!exec moneyprint $your_wims_item_list $precision_word\nexample:\nmoney=!exec moneyprint 1.2,30.1,.4,-.23123456 2\nThe result is a comma separated list: 1.20,30.10,0.40,-0.23\n using 2 decimals\nNote: no calculations are done.\nNo spaces allowed \n"); |
||
76 | exit(0); |
||
77 | } |
||
78 | /* test for illegal characters */ |
||
79 | const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|"; |
||
80 | /* +-*^XxEe are allowed : 12.34e+05 12.34e-08 1x10^5 1.234*10^123*/ |
||
81 | char *input; |
||
82 | input = argv[1]; |
||
83 | while (*input){ |
||
84 | if ( strchr(invalid_characters, *input) ){ |
||
85 | fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input); |
||
86 | exit(0); |
||
87 | } |
||
88 | input++; |
||
89 | } |
||
90 | int DECIMALS; |
||
91 | if(argv[2] != NULL){ |
||
92 | DECIMALS = atoi(argv[2]); |
||
93 | if(DECIMALS > MAX_DIGITS){ |
||
94 | fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0); |
||
95 | } |
||
96 | } |
||
97 | else |
||
98 | { |
||
99 | DECIMALS = 2; |
||
100 | } |
||
101 | char *sep = ","; |
||
102 | char *ptr; |
||
103 | char word[MAX_DIGITS]; |
||
104 | char exponent[MAX_DIGITS]; |
||
105 | char number[MAX_DIGITS]; |
||
106 | char *w_use_comma = getenv("w_use_comma"); |
||
107 | if( w_use_comma == NULL ){ w_use_comma = "0";} |
||
108 | int cnt = 1;int powE = 0;int idx1 = 0;int idx2 = 0;int length = 0;int i = 0;int pow10 = 0; |
||
109 | double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */ |
||
110 | double ascii_number; |
||
111 | input = argv[1]; |
||
112 | ptr = strtok(input,","); |
||
113 | while( ptr != NULL){ |
||
114 | if( cnt > MAX_CONV ){fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);exit(0);} |
||
115 | /* next item in input argv[1] */ |
||
13927 | schaersvoo | 116 | strlcpy( word, ptr, sizeof(word)); |
12199 | schaersvoo | 117 | length = strlen(ptr); |
118 | if(length > MAX_DIGITS-1){fprintf(stdout,"ERROR string too large\n");exit(0);} |
||
119 | /* reset counters */ |
||
120 | powE = 0;pow10 = 0;idx1 = 0;idx2 = 0;i = 0; |
||
121 | for( i = 0; i < length ; i++){ |
||
122 | if(powE > 1 ){ fprintf(stdout,"ERROR in syntax\n");exit(0);} |
||
123 | if( idx1 + idx2 > MAX_DIGITS-1){ fprintf(stdout,"ERROR string too large\n");exit(0);} |
||
124 | switch( word[i] ){ |
||
125 | case '+' : break; /* do not use 10^+2 */ |
||
126 | case 'e' : powE++;break; |
||
127 | case 'E' : powE++;break; |
||
128 | case 'x' : pow10++;break; |
||
129 | case '*' : pow10++;break; |
||
130 | /* word[2] = '^' --> 10^5 => 1.00*10^5 */ |
||
131 | case '^' : if( i != 2 ){ pow10 = 5; }else{ idx1 = 1;idx2 = 0;pow10 = 4;} break; |
||
132 | default : if( pow10 > 0 ){ |
||
133 | pow10++; |
||
134 | if( pow10 > 4 ){ /* *10^ = 4 chars */ |
||
135 | exponent[idx2] = word[i]; |
||
136 | idx2++; |
||
5416 | schaersvoo | 137 | } |
12199 | schaersvoo | 138 | } |
139 | else |
||
140 | { |
||
141 | if(powE > 0){ |
||
142 | exponent[idx2] = word[i]; |
||
143 | idx2++; |
||
144 | } |
||
5416 | schaersvoo | 145 | else |
12199 | schaersvoo | 146 | { |
147 | number[idx1] = word[i]; |
||
148 | idx1++; |
||
5416 | schaersvoo | 149 | } |
12199 | schaersvoo | 150 | } |
151 | break; |
||
152 | } |
||
153 | } |
||
154 | exponent[idx2] = '\0'; |
||
155 | number[idx1] = '\0'; |
||
156 | /* atof needs decimal point locale, like "C" */ |
||
157 | setlocale(LC_NUMERIC, "C"); |
||
158 | ascii_number = atof(number); |
||
159 | if( ascii_number > 0 ){ ascii_number = ascii_number + correction;}else{ ascii_number = ascii_number - correction; } |
||
160 | if ( strcmp( w_use_comma , "1") == 0 ){ setlocale(LC_NUMERIC, LOCALE);sep = " "; } |
||
161 | if( powE == 1 || pow10> 0 ){ |
||
162 | if(cnt > 1){ |
||
163 | fprintf( stdout , "%s%.*f*10^%s" ,sep, DECIMALS , ascii_number , exponent ); |
||
164 | } |
||
165 | else |
||
166 | { |
||
167 | fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent ); |
||
168 | } |
||
169 | } |
||
170 | else |
||
171 | { |
||
172 | if(cnt > 1 ){ |
||
173 | fprintf( stdout , "%s%.*f" ,sep, DECIMALS , ascii_number); |
||
174 | } |
||
175 | else |
||
176 | { |
||
177 | fprintf( stdout , "%.*f" , DECIMALS , ascii_number); |
||
178 | } |
||
179 | } |
||
180 | cnt++; |
||
181 | ptr = strtok(NULL,","); |
||
182 | } |
||
183 | fprintf(stdout,"\n"); |
||
184 | return 0; |
||
3519 | schaersvoo | 185 | } |