Subversion Repositories wimsdev

Rev

Rev 14856 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2. *********************************************************************************
  3. * J.M. Evers 3/2012              *
  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  *
  7. * No warrenty whatsoever              *
  8. *********************************************************************************
  9. general use:
  10. rounding to 2 decimals (financial math)
  11. tot=!exec moneyprint 0.1,17,123.4,123.99765
  12. tot -> 0.10,17.00,123.40,124.00
  13.  
  14. 2/2012
  15.  modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers
  16.  tot=!exec moneyprint 2.1,4.123,5  2   // 2 decimals
  17.  tot -> 2.10,4.12,5.00
  18.  tot=!exec moneyprint 2.1,4.123,5  4   // 4 decimals
  19.  tot -> 2.1000,4.1230,5.0000
  20.  tot=!exec moneyprint 2.1,4.123,5
  21.  tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals
  22.  
  23. 6/2012.
  24.  modified again to support rounding of scientific numbers, like
  25.  tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3
  26.  tot -> 1.235e06,1.235e6,0.012e-23
  27.  
  28.  assumed only powers of 10 [scientific notation]
  29.  
  30. 12/2012
  31. Modified : using only 10^ in powers
  32. (e+8 -> *10^8 ; e-8 -> *10^-8)
  33. Extra syntax error signal (using more than 1 'e')
  34.  
  35. 27/2014
  36. Modified avoiding truncating of numbers like 15.625 --> 16.62
  37. 4/2020
  38. Modified to use ";" and "," as separators...preserving the sequence
  39. moneyprint 1,2,3;4,5,6;7,8,9 -> 1.00,2.00,3.00;4.00,5.00,6.00;7.00,8.00,9.00
  40. */
  41.  
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <math.h>
  47. #define MAX_DIGITS 32
  48. #define MAX_CONV 32
  49.  
  50. int main( int argc, char *argv[]){
  51.   if( argc != 2 && argc != 3){
  52.     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");
  53.     exit(0);
  54.   }
  55.   /* test for illegal characters */
  56.   const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{}:~><?/\\|";
  57.   /* ;+-*^XxEe are allowed : 12.34e+05  12.34e-08 1x10^5 1.234*10^123*/
  58.   char *input;
  59.   input = argv[1];
  60.   while (*input){
  61.     if ( strchr(invalid_characters, *input) ){
  62.       fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input);
  63.       exit(0);
  64.     }
  65.     input++;
  66.   }
  67.   int DECIMALS;
  68.   if(argv[2] != NULL){
  69.     DECIMALS = atoi(argv[2]);
  70.     if(DECIMALS > MAX_DIGITS){
  71.       fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0);
  72.     }
  73.   }
  74.   else DECIMALS = 2;
  75.   char *ptr;
  76.   char word[MAX_DIGITS];
  77.   char exponent[MAX_DIGITS];
  78.   char number[MAX_DIGITS];
  79.   int cnt = 0;
  80.   int powE = 0;
  81.   int idx1 = 0;
  82.   int idx2 = 0;
  83.   int length= 0;
  84.   int i = 0;
  85.   int pow10 = 0;
  86.   double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */
  87.   double ascii_number;
  88.   input = argv[1];
  89.   /* 14/4/2020 replace ';' by ','  BPR */
  90.   int idx3[MAX_CONV];
  91.   for(i = 0; i < strlen(input); i++){
  92.     if(input[i] == ';'){
  93.       input[i] = ','; idx3[cnt] = 1; cnt++;
  94.     }
  95.     else
  96.       if(input[i] == ',' ){ idx3[cnt] = 0; cnt++;}
  97.   }
  98.   char *sep = ",";
  99.   cnt = 1;
  100.   ptr = strtok(input,",");
  101.   while( ptr != NULL){
  102.     if( cnt > MAX_CONV ){
  103.       fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);
  104.       exit(0);
  105.     }
  106.     /* next item in input argv[1] */
  107.     strncpy( word, ptr, MAX_DIGITS-1);
  108.     length = strlen(ptr);
  109.     if(length > MAX_DIGITS-1){
  110.       fprintf(stdout,"ERROR string too large\n");
  111.       exit(0);
  112.     }
  113.     /* reset counters */
  114.     powE = 0;
  115.     pow10 = 0;
  116.     idx1 = 0;
  117.     idx2 = 0;
  118.     i = 0;
  119.     for( i = 0; i < length ; i++){
  120.       if(powE > 1 ){
  121.         fprintf(stdout,"ERROR in syntax\n");
  122.         exit(0);
  123.       }
  124.       if( idx1 + idx2  >  MAX_DIGITS-1){
  125.         fprintf(stdout,"ERROR string too large\n");
  126.         exit(0);
  127.       }
  128.       switch( word[i] ){
  129.         case '+' : break; /* do not use 10^+2 */
  130.         case 'e' : powE++;break;
  131.         case 'E' : powE++;break;
  132.         case 'x' : pow10++;break;
  133.         case '*' : pow10++;break;
  134.         case '^' : pow10=5;break;
  135.         default  :
  136.         if( pow10 > 0 ){
  137.           pow10++;
  138.           if( pow10 > 4 ){ /*  *10^ = 4 chars */
  139.             exponent[idx2] = word[i];
  140.             idx2++;
  141.           }
  142.         }
  143.         else
  144.         {
  145.           if(powE > 0){
  146.             exponent[idx2] = word[i]; idx2++;}
  147.           else {
  148.             number[idx1] = word[i]; idx1++;}
  149.         }
  150.         break;
  151.       }
  152.     }
  153.     exponent[idx2] = '\0';
  154.     number[idx1] = '\0';
  155.     ascii_number = atof(number);
  156.     if( ascii_number > 0 )
  157.       ascii_number = ascii_number + correction;
  158.     else
  159.       ascii_number = ascii_number - correction;
  160.     if( powE == 1 || pow10> 0 ){
  161.       if(cnt > 1)
  162.         fprintf( stdout, "%s%.*f*10^%s", sep, DECIMALS, ascii_number, exponent );
  163.       else
  164.         fprintf( stdout, "%.*f*10^%s", DECIMALS, ascii_number, exponent );
  165.     }
  166.     else {
  167.       if(cnt > 1 )
  168.         fprintf( stdout, "%s%.*f", sep, DECIMALS, ascii_number);
  169.       else
  170.         fprintf( stdout, "%.*f", DECIMALS, ascii_number);
  171.     }
  172.     if(idx3[cnt-1] == 1 ) sep = ";"; else sep = ",";
  173.     cnt++;
  174.     ptr = strtok(NULL,",");
  175.   }
  176.   fprintf(stdout,"\n");
  177.   return 0;
  178. }
  179.