Subversion Repositories wimsdev

Compare Revisions

Ignore whitespace Rev 13928 → Rev 13932

/trunk/wims/src/Misc/moneyprint/moneyprint.c
1,30 → 1,16
/*
*********************************************************************************
* J.M. Evers 2/2012 *
* J.M. Evers 3/2012 *
* This is all amateur scriblings... So no copyrights. *
* This source code file, and compiled objects derived from it, *
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatsoever *
*********************************************************************************
general use:
rounding to 2 decimals (financial math)
tot=!exec moneyprint 0.1,17,123.4,123.99765
tot -> 0.10,17.00,123.40,124.00
 
general use:
moneyprint number1,number2,number3... DECIMALS
default rounding to 2 decimals (financial math)
 
tot=!exec moneyprint 6.14512 --> 6.15
tot=!exec moneyprint 6.14512 3 --> 6.145
tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0.10,17.00,123.40,124.00
tot=!exec moneyprint 2*10^7,2E-7 --> 2.00*10^7,2.00*10^-7
!set use_comma
# only for representation ,the outcome can not be used for further arithmetics/calculations
tot=!exec moneyprint 6.14512 --> 6,15
tot=!exec moneyprint 6.14512 3 --> 6,145
tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0,10 17,00 123,40 124,00
tot=!exec moneyprint 2*10^7,2E-7 --> 2,00*10^7 2,00*10^-7
 
bugs & flaws: no calculations are performed , fractions are not supported
 
CHANGELOG
2/2012
modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers
tot=!exec moneyprint 2.1,4.123,5 2 // 2 decimals
34,29 → 20,21
tot=!exec moneyprint 2.1,4.123,5
tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals
 
6/2012
6/2012.
modified again to support rounding of scientific numbers, like
tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3
tot -> 1.235e06,1.235e6,0.012e-23
assumed only powers of 10 [scientific notation]
12/2012
Modified : using only 10^ in powers
(e+8 -> *10^8 ; e-8 -> *10^-8)
Extra syntax error signal (using more than 1 'e')
Modified : using only 10^ in powers
(e+8 -> *10^8 ; e-8 -> *10^-8)
Extra syntax error signal (using more than 1 'e')
 
27/2014
Modified avoiding truncating of numbers like 15.625 --> 16.62
Modified avoiding truncating of numbers like 15.625 --> 16.62
 
2/2018
if variable "w_use_comma" is set (eg in phtml !set use_comma=1), the result is a comma 'decimal' separator:
moneyprint 1.2345 2 -> 1,23
moneyprint 1.2345 , 2.34567 , 3.4567 , 5 2 -> 1,23 2,35 3,46 5,00
(note: in this case (multiple conversions) we use 'spaces' instead of an item ',' list )
This is INCOMPATIBLE with calculating software : only suitable for REPRESENTATION of (money) numbers
If env. variable w_use_comma is not set or not "1" , the behaviour is a number with a decimal point
 
5/2019 use "strlcpy, strlcat" - size-bounded string copying and concatenation
*/
 
#include <stdio.h>
63,123 → 41,142
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <locale.h>
 
#define MAX_DIGITS 128
#define MAX_DIGITS 32
#define MAX_CONV 32
#define LOCALE "fr_FR.ISO8859-1"
 
 
int main( int argc , char *argv[]){
if( argc != 2 && argc != 3){
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");
exit(0);
}
/* test for illegal characters */
const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|";
/* +-*^XxEe are allowed : 12.34e+05 12.34e-08 1x10^5 1.234*10^123*/
char *input;
input = argv[1];
while (*input){
if ( strchr(invalid_characters, *input) ){
fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input);
exit(0);
}
input++;
}
int DECIMALS;
if(argv[2] != NULL){
DECIMALS = atoi(argv[2]);
if(DECIMALS > MAX_DIGITS){
fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0);
}
}
else
{
DECIMALS = 2;
}
char *sep = ",";
char *ptr;
char word[MAX_DIGITS];
char exponent[MAX_DIGITS];
char number[MAX_DIGITS];
char *w_use_comma = getenv("w_use_comma");
if( w_use_comma == NULL ){ w_use_comma = "0";}
int cnt = 1;int powE = 0;int idx1 = 0;int idx2 = 0;int length = 0;int i = 0;int pow10 = 0;
double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */
double ascii_number;
input = argv[1];
ptr = strtok(input,",");
while( ptr != NULL){
if( cnt > MAX_CONV ){fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);exit(0);}
/* next item in input argv[1] */
strlcpy( word, ptr, sizeof(word));
length = strlen(ptr);
if(length > MAX_DIGITS-1){fprintf(stdout,"ERROR string too large\n");exit(0);}
/* reset counters */
powE = 0;pow10 = 0;idx1 = 0;idx2 = 0;i = 0;
for( i = 0; i < length ; i++){
if(powE > 1 ){ fprintf(stdout,"ERROR in syntax\n");exit(0);}
if( idx1 + idx2 > MAX_DIGITS-1){ fprintf(stdout,"ERROR string too large\n");exit(0);}
switch( word[i] ){
case '+' : break; /* do not use 10^+2 */
case 'e' : powE++;break;
case 'E' : powE++;break;
case 'x' : pow10++;break;
case '*' : pow10++;break;
/* word[2] = '^' --> 10^5 => 1.00*10^5 */
case '^' : if( i != 2 ){ pow10 = 5; }else{ idx1 = 1;idx2 = 0;pow10 = 4;} break;
default : if( pow10 > 0 ){
pow10++;
if( pow10 > 4 ){ /* *10^ = 4 chars */
exponent[idx2] = word[i];
idx2++;
if( argc != 2 && argc != 3){
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");
exit(0);
}
/* test for illegal characters */
const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|";
/* +-*^XxEe are allowed : 12.34e+05 12.34e-08 1x10^5 1.234*10^123*/
char *input;
input = argv[1];
while (*input){
if ( strchr(invalid_characters, *input) ){
fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input);
exit(0);
}
input++;
}
int DECIMALS;
if(argv[2] != NULL){
DECIMALS = atoi(argv[2]);
if(DECIMALS > MAX_DIGITS){
fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0);
}
}
else
{
DECIMALS = 2;
}
char *ptr;
char word[MAX_DIGITS];
char exponent[MAX_DIGITS];
char number[MAX_DIGITS];
int cnt = 1;
int powE = 0;
int idx1 = 0;
int idx2 = 0;
int length= 0;
int i = 0;
int pow10 = 0;
double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */
double ascii_number;
input = argv[1];
ptr = strtok(input,",");
while( ptr != NULL){
if( cnt > MAX_CONV ){
fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);
exit(0);
}
// next item in input argv[1]
strncpy( word, ptr, MAX_DIGITS);
length = strlen(ptr);
if(length > MAX_DIGITS-1){
fprintf(stdout,"ERROR string too large\n");
exit(0);
}
//reset counters
powE = 0;
pow10 = 0;
idx1 = 0;
idx2 = 0;
i = 0;
for( i = 0; i < length ; i++){
if(powE > 1 ){
fprintf(stdout,"ERROR in syntax\n");
exit(0);
}
if( idx1 + idx2 > MAX_DIGITS-1){
fprintf(stdout,"ERROR string too large\n");
exit(0);
}
switch( word[i] ){
case '+' : break; /* do not use 10^+2 */
case 'e' : powE++;break;
case 'E' : powE++;break;
case 'x' : pow10++;break;
case '*' : pow10++;break;
case '^' : pow10=5;break;
default :
if( pow10 > 0 ){
pow10++;
if( pow10 > 4 ){ /* *10^ = 4 chars */
exponent[idx2] = word[i];
idx2++;
}
}
}
else
{
if(powE > 0){
exponent[idx2] = word[i];
idx2++;
}
else
{
number[idx1] = word[i];
idx1++;
{
if(powE > 0){
exponent[idx2] = word[i];
idx2++;
}
else
{
number[idx1] = word[i];
idx1++;
}
}
}
break;
}
}
exponent[idx2] = '\0';
number[idx1] = '\0';
/* atof needs decimal point locale, like "C" */
setlocale(LC_NUMERIC, "C");
ascii_number = atof(number);
if( ascii_number > 0 ){ ascii_number = ascii_number + correction;}else{ ascii_number = ascii_number - correction; }
if ( strcmp( w_use_comma , "1") == 0 ){ setlocale(LC_NUMERIC, LOCALE);sep = " "; }
if( powE == 1 || pow10> 0 ){
if(cnt > 1){
fprintf( stdout , "%s%.*f*10^%s" ,sep, DECIMALS , ascii_number , exponent );
}
else
{
fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent );
}
}
else
{
if(cnt > 1 ){
fprintf( stdout , "%s%.*f" ,sep, DECIMALS , ascii_number);
}
else
{
fprintf( stdout , "%.*f" , DECIMALS , ascii_number);
}
}
cnt++;
ptr = strtok(NULL,",");
}
fprintf(stdout,"\n");
return 0;
break;
}
}
exponent[idx2] = '\0';
number[idx1] = '\0';
ascii_number = atof(number);
if( ascii_number > 0 ){
ascii_number = ascii_number + correction;
}
else
{
ascii_number = ascii_number - correction;
}
if( powE == 1 || pow10> 0 ){
if(cnt > 1){
fprintf( stdout , ",%.*f*10^%s" , DECIMALS , ascii_number , exponent );
}
else
{
fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent );
}
}
else
{
if(cnt > 1 ){
fprintf( stdout , ",%.*f" , DECIMALS , ascii_number);
}
else
{
fprintf( stdout , "%.*f" , DECIMALS , ascii_number);
}
}
cnt++;
ptr = strtok(NULL,",");
}
fprintf(stdout,"\n");
return 0;
}
 
/trunk/wims/src/Misc/toascii/toascii.c
6,8 → 6,6
* can be used and distributed without restriction, including for commercial use *
* No warrenty whatoever *
*********************************************************************************
 
7/5/2019 use strlcpy, strlcat - size-bounded string copying and concatenation
*/
 
#include <stdio.h>
38,7 → 36,7
}
else
{
strlcpy( word, ptr, sizeof(word) ) ;
strncpy( word, ptr, length ) ;
total = 0;
for( i = 0;i < length ;i++ ){
total = total + word[i];
50,3 → 48,4
fprintf(stdout,"\n");
return 0 ;
}